This is an R Markdown Notebook. When you execute code within the notebook, the results appear beneath the code.

Try executing this chunk by clicking the Run button within the chunk or by placing your cursor inside it and pressing Ctrl+Shift+Enter.

Add a new chunk by clicking the Insert Chunk button on the toolbar or by pressing Ctrl+Alt+I.

When you save the notebook, an HTML file containing the code and output will be saved alongside it (click the Preview button or press Ctrl+Shift+K to preview the HTML file).

The preview shows you a rendered HTML copy of the contents of the editor. Consequently, unlike Knit, Preview does not run any R code chunks. Instead, the output of the chunk when it was last run in the editor is displayed.

setwd("D:/R program")
The working directory was changed to D:/R program inside a notebook chunk. The working directory will be reset when the chunk is finished running. Use the knitr root.dir option in the setup chunk to change the working directory for notebook chunks.
#values needed 
K= 1.38064852*(10)^-23 #m2 kg/ s2 K boltzmann constant
mu= 1.126*(10)^-3 #kg/m s dynamic viscosity in 18C
v= 1.099*(10)^-6 #m2/s kinematic viscosity in 18C
Reh_calc= 2.3E-6 #in m radius Ehux
Reh_naked= 1.8E-6 #in m radius Ehux
Rehv= 90*(10)^-9 #in m radius virus
Temp = 18+273.15 #temp in kelvin, here assuming 18C
Den_OcM = 1.05 #g/cm3 density organic cell matter
Den_CH2O= 1.025 #g/cm3 density seawater at 18C
hostnum <- (10)^3
virnum <- hostnum*5
require (ggplot2)
require(plotly)
require(grid)
require(ggthemes)
require (dplyr)
require(plyr)
source ("theme_Publication.R")
source("resizewin.R")
#resize.win(12,9)
grid.newpage()

for Brownian motion

#Brownian motion (BM)
#1. make a data frame
BM <- data.frame (group= c("naked", "calcified"), rad= c(1.8E-6, 2.3E-6)) 
#2. calculate beta (beta)
BM$beta_s <- (2*(K*(10)^4)*Temp*(((BM$rad+Rehv)*100)^2))/((3*mu*10)*(BM$rad*Rehv*1e4)) #m3/s
BM$beta_d <- BM$beta_s*86400 #to cm3/day
# go back to this later
#3. calculate encounters (E)
BM$E <- BM$beta_d*hostnum
BM$E_HV <- BM$beta_d*virnum*hostnum
BM

Differential settling (DS)

#Differential settling (DS)
#1. read in PIC data
library(readr) #always use readr not baseR
setwd("D:/R program")
The working directory was changed to D:/R program inside a notebook chunk. The working directory will be reset when the chunk is finished running. Use the knitr root.dir option in the setup chunk to change the working directory for notebook chunks.
PIC <- read_csv("Postdoc-R/CSV Files/PIC.csv")
Parsed with column specification:
cols(
  Strain = col_character(),
  Replicate = col_integer(),
  TC = col_double(),
  AC = col_double(),
  Cellcount = col_double()
)
PIC$Strain <- as.factor(PIC$Strain)
PIC$Replicate <- as.factor(PIC$Replicate)
#certain changes in data.table API made calculating inside the list data.table to not work
#2. calculate PIC
PIC$PIC <- PIC$TC-PIC$AC
PIC$PICpercell <- (PIC$PIC/PIC$Cellcount)*(10)^-3#in g
PIC$PICpercellpg <- PIC$PICpercell*1e12
PIC$TCpg <- (PIC$TC/PIC$Cellcount)*(10)^-3*1e12 #what if total carbon is used for calculating density
ggplotly(ggplot(data=PIC, aes(x=Strain, y=PICpercellpg)) + geom_boxplot()+geom_point(size=2) +theme_Publication())

ggplotly(ggplot(data=PIC, aes(x=Strain, y=TCpg)) + geom_boxplot()+geom_point(size=2) +theme_Publication())
#3. calculate density of cells (den)
PIC <- mutate(PIC, group = ifelse(PICpercellpg < 4 , "naked", "calcified"))
ggplotly(ggplot(data=PIC, aes(x=group, y=PICpercellpg)) + geom_boxplot()+geom_point(size=2, aes(color=Strain))+
           theme_Publication())
plotly.js does not (yet) support horizontal legend items 
You can track progress here: 
https://github.com/plotly/plotly.js/issues/53 

PIC <- mutate(PIC, rad = ifelse(group == "naked" ,  1.8E-6,  2.3E-6)) #in m
PIC$volume <- (4/3)*pi*(PIC$rad*100)^3 #in cm3
PIC$Den_cell2 <- (PIC$TCpg*1e-12)/PIC$volume #g/cm3, if TC is used density, total density (below) becomes really big (i.e., max 2 g/cm3 which is not reasonable)
PIC$Den_cell <- PIC$PICpercell/PIC$volume #g/cm3
PIC$Den_celltotal <- PIC$Den_cell+Den_OcM
ggplotly(ggplot(data=PIC, aes(x=Strain, y=Den_celltotal, color=group)) + geom_boxplot()+geom_point(size=2) 
         +theme_Publication())
plotly.js does not (yet) support horizontal legend items 
You can track progress here: 
https://github.com/plotly/plotly.js/issues/53 

#some strains that are "naked" have PIC<2. I chose to ignore this since in the lm model I do not use
#strain as a factor, rather data is treated as a whole (e.g., no grouping)
#4. calculate sinking velocity of cells
PIC$SinkVel <- ((2*((PIC$rad*100)^2)*(981)*(PIC$Den_celltotal-Den_CH2O))/(9*(mu*10)))*864 #meter per day
#g is converted to per day, 864 is the one that converts cm/s to m/day
#plot sinking velocity vs calcification
ggplot(data=PIC, aes(x=PICpercellpg, y=SinkVel, color=Strain, shape=group)) + geom_point(size=5)+theme_Publication()+
    labs(y = expression("Sinking velocity"~("m"~day^-1)), x = expression("PIC"~cell^-1)) +
    scale_y_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=2),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) + annotation_logticks(sides="l")

#5. calculate sinkvel of viruses
Den_virus <- 1.09 #data from Ben D. fresh EhV-207 density. old density of EhV-207 is 1.19
Ehv_SinkVel <- ((2*((Rehv*100)^2)*(981)*(Den_virus-Den_CH2O))/(9*(mu*10)))*864  #equals to 0
#6. calculate beta kernels
PIC$beta_s <- pi*(((PIC$rad+Rehv)*100)^2)*(abs((PIC$SinkVel-Ehv_SinkVel)/864)) #in encounters cm3/s
PIC$beta_d <- PIC$beta_s*86400 #in cm3/day
Sinkvelbeta.plot<- ggplot(data=PIC, aes(x=SinkVel, y=beta_d, color=Strain, shape=group)) + geom_point(size=5)+
  theme_Publication()+
  labs(x = expression("Sinking velocity"~("m"~day^-1)), y = expression(beta~("Encounters" ~ cm^3~day^-1))) +
 scale_y_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=2),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) + annotation_logticks(sides="l")
Sinkvelbeta.plot #change ticks

#ggplotly(Sinkvelbeta.plot)
ggplotly(ggplot(data=PIC, aes(x=Strain, y=SinkVel)) + geom_boxplot()+theme_Publication())

ggplot(data=PIC, aes(x=PICpercellpg, y=beta_d, color=Strain)) + geom_point(size=5)+theme_Publication()+
  labs(y = expression(beta~("Encounters"~cm^3~day^-1)), x = expression("PIC"~cell^-1))  +
scale_y_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=2),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) + annotation_logticks(sides="l")

#7. calculate beta and encounters
#beta are in cells cm3/ day then encounters are to cells/cm3 day
PIC$E_DS_HV <- (PIC$beta_d*virnum*hostnum)  #E calculated with Virus and Host (10:1 MOI)
PIC$E_DS_V <- (PIC$beta_d*virnum) #E calculated with Virus
#8. calculate for lith parameters
lithvol <- 3*1e-12 #in cm3, from CJ's paper
PIC$perlith <- PIC$PICpercell/20 #in g, assuming 20 liths attached
PIC$perlithpg <- PIC$perlith*1e12 #in pg
PIC$Denlith <- (PIC$perlith/lithvol) + Den_OcM #in g/cm3, with organic matter attached
PIC$Denlith_noOCM <- (PIC$perlith/lithvol) #in g/cm3, with organic matter attached
rad_lith <- 2E-6 #in m radius
PIC$SinkVel_lith <- ((2*((rad_lith*100)^2)*(981)*(PIC$Denlith-Den_CH2O))/(9*(mu*10)))*864 #meter per day
PIC$beta_s_lith <- pi*(((rad_lith+Rehv)*100)^2)*(abs((PIC$SinkVel_lith-Ehv_SinkVel)/864)) #in encounters cm3/s
PIC$beta_d_lith <- PIC$beta_s_lith*86400 #in cm3/day
ggplot(data=PIC, aes(x=perlithpg, y=SinkVel_lith, color=Strain, shape=group)) + geom_point(size=5)+theme_Publication()+
  labs(y = expression("Sinking velocity"~("m"~day^-1)), x = expression("PIC"~lith^-1)) 

PIC$Elith_DS_HV <- (PIC$beta_d_lith*virnum*hostnum)  #E calculated with Virus and Host (10:1 MOI)
PIC$Elith_DS_V <- (PIC$beta_d_lith*virnum) #E calculated with Virus
require (dplyr)
PIC$group2 <- case_when(
  PIC$PICpercellpg <2  ~ "naked_bouyant",
  PIC$PICpercellpg >2 & PIC$PICpercellpg < 4 ~ "naked/calcified uncertain",
  PIC$PICpercellpg >4 & PIC$PICpercellpg < 10 ~ "moderately calcified",
  PIC$PICpercellpg >10 ~ "strongly calcified", 
  TRUE ~ as.character(PIC$PICpercellpg)
)
breaks <- 10^(-10:10)
ggplot(data=PIC, aes(x=SinkVel, y=E_DS_HV, color=Strain, shape=group)) + geom_point(size=5)+theme_Publication()+
 scale_y_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=2),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) + annotation_logticks(sides="l")

ggplot(data=PIC, aes(x=SinkVel, y=E_DS_V, color=Strain, shape=group)) + geom_point(size=5)+theme_Publication()+
  scale_y_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=2),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) + annotation_logticks(sides="l")

ggplot(data=PIC, aes(x=SinkVel_lith, y=Elith_DS_V, color=Strain, shape=group)) + geom_point(size=5) + 
  theme_Publication() + scale_y_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=3),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) + annotation_logticks(sides="l")

summary_DS <- ddply(PIC, .(Strain), summarize,  PICpercellpg=mean(PICpercellpg), perlithpg = mean(perlithpg), 
                    Den_celltotal = mean (Den_celltotal),
                    SinkVel=mean(SinkVel),beta_d=mean(beta_d), E_DS_V= mean(E_DS_V), E_DS_HV=mean(E_DS_HV),
                    SinkVel_lith=mean (SinkVel_lith), beta_d_lith=mean (beta_d_lith), Elith_DS_HV=mean (Elith_DS_HV),
                    Elith_DS_V=mean (Elith_DS_V))
summary_DS_bygroup <- ddply(PIC, .(group2), summarize,  PICpercellpg=mean(PICpercellpg), perlithpg = mean(perlithpg), 
                            Den_celltotal = mean (Den_celltotal),
                            SinkVel=mean(SinkVel),beta_d=mean(beta_d), E_DS_V= mean(E_DS_V), E_DS_HV=mean(E_DS_HV), 
                            SinkVel_lith=mean (SinkVel_lith), beta_d_lith=mean (beta_d_lith), 
                            Elith_DS_HV=mean (Elith_DS_HV), Elith_DS_V=mean (Elith_DS_V))
summary_DS
summary_DS_bygroup
setwd("D:/R program")
The working directory was changed to D:/R program inside a notebook chunk. The working directory will be reset when the chunk is finished running. Use the knitr root.dir option in the setup chunk to change the working directory for notebook chunks.
require(openxlsx)
Loading required package: openxlsx
write.xlsx(summary_DS, file = "Postdoc-R/Exported Tables/summary_DS.xlsx")
write.xlsx(summary_DS_bygroup, file = "Postdoc-R/Exported Tables/summary_DS_bygroup.xlsx")
#9. regression of PIC and sinkvel of cells and liths
#a. for cells
PIC_reg <- lm(SinkVel~PICpercellpg, data=PIC) #essentially perfect fit: summary may be unreliable haha
summary(PIC_reg)

Call:
lm(formula = SinkVel ~ PICpercellpg, data = PIC)

Residuals:
       Min         1Q     Median         3Q        Max 
-0.0115036 -0.0029329  0.0004329  0.0021756  0.0113796 

Coefficients:
              Estimate Std. Error t value Pr(>|t|)    
(Intercept)  0.0180085  0.0009620   18.72   <2e-16 ***
PICpercellpg 0.0177476  0.0001254  141.58   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.005175 on 44 degrees of freedom
Multiple R-squared:  0.9978,    Adjusted R-squared:  0.9978 
F-statistic: 2.004e+04 on 1 and 44 DF,  p-value: < 2.2e-16
plot(residuals.lm(PIC_reg))
layout(matrix(1:4,2,2))

plot(PIC_reg)

coef(PIC_reg)
 (Intercept) PICpercellpg 
  0.01800852   0.01774764 
# coef(PIC_reg)
#(Intercept) PICpercellpg 
#0.01800852   0.01774764 
cor(PIC$PICpercellpg, PIC$SinkVel)
[1] 0.9989042
#cor = 0.9989042
beta_reg <- lm(beta_d~PICpercellpg, data=PIC)
plot(residuals.lm(beta_reg))
coef(beta_reg)
 (Intercept) PICpercellpg 
1.639233e-07 3.243054e-07 
#coef(beta_reg)
# (Intercept) PICpercellpg 
#1.639233e-07 3.243054e-07
E_DS_HV_reg <- lm(E_DS_HV~PICpercellpg, data=PIC)
E_DS_V_reg <- lm(E_DS_V~PICpercellpg, data=PIC)
plot(residuals.lm(E_DS_HV_reg))
plot(residuals.lm(E_DS_V_reg))
coef(E_DS_HV_reg)
 (Intercept) PICpercellpg 
   0.8196165    1.6215272 
coef(E_DS_V_reg)
 (Intercept) PICpercellpg 
0.0008196165 0.0016215272 
#b. for liths
perlith_reg <- lm (perlithpg~PICpercellpg, data=PIC)
plot(resid(perlith_reg))

coef(perlith_reg)
  (Intercept)  PICpercellpg 
-6.547738e-17  5.000000e-02 
sinkvel_lith_reg <- lm(SinkVel_lith~PICpercellpg, data = PIC)
summary(sinkvel_lith_reg)
essentially perfect fit: summary may be unreliable

Call:
lm(formula = SinkVel_lith ~ PICpercellpg, data = PIC)

Residuals:
       Min         1Q     Median         3Q        Max 
-1.043e-16 -3.686e-17 -2.422e-18  4.040e-17  7.364e-17 

Coefficients:
              Estimate Std. Error   t value Pr(>|t|)    
(Intercept)  1.673e-02  8.512e-18 1.965e+15   <2e-16 ***
PICpercellpg 1.115e-02  1.109e-18 1.005e+16   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 4.579e-17 on 44 degrees of freedom
Multiple R-squared:      1, Adjusted R-squared:      1 
F-statistic: 1.011e+32 on 1 and 44 DF,  p-value: < 2.2e-16
plot(residuals.lm(sinkvel_lith_reg))
layout(matrix(1:4,2,2))

plot(sinkvel_lith_reg)

coef(sinkvel_lith_reg)
 (Intercept) PICpercellpg 
  0.01672753   0.01115169 
beta_lith_reg <- lm(beta_d_lith~PICpercellpg, data=PIC)
plot(residuals.lm(beta_lith_reg))
coef(beta_lith_reg)
 (Intercept) PICpercellpg 
2.302277e-07 1.528542e-07 
Elith_DS_HV_reg <- lm(Elith_DS_HV~PICpercellpg, data=PIC)
Elith_DS_V_reg <- lm(Elith_DS_V~PICpercellpg, data=PIC)
plot(residuals.lm(Elith_DS_HV_reg))
plot(residuals.lm(Elith_DS_V_reg))

coef(Elith_DS_HV_reg)
 (Intercept) PICpercellpg 
    1.151139     0.764271 
coef(Elith_DS_V_reg)
 (Intercept) PICpercellpg 
 0.001151139  0.000764271 
# 9. make new dataframe depending on experimental PIC values
# make a prediction based on PIC values
require(truncnorm)
Loading required package: truncnorm
require(Rmisc)
Loading required package: Rmisc
Loading required package: lattice
summary(PIC$PICpercellpg)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
-1.5873  0.5523  2.3009  4.6739  6.1204 20.1442 
summarySE(data=PIC, measurevar="PICpercellpg")
PIC_newdata <- as.data.frame(rtruncnorm(n=1000, a=-1.6, b=20.14, mean=4.7, sd=6.15))
#rename column. rename function in plyr 
library(plyr)
PIC_newdata <- rename (PIC_newdata, c ("rtruncnorm(n = 1000, a = -1.6, b = 20.14, mean = 4.7, sd = 6.15)" = 
                                         "PICpercellpg"))
PIC_newdata <- mutate(PIC_newdata, group = ifelse(PICpercellpg < 4 , "naked", "calcified"))
ggplotly(ggplot(data=PIC_newdata, aes(x=group, y=PICpercellpg)) + geom_boxplot()+geom_point(size=2) +
           theme_Publication())

PIC_newdata$group2 <- case_when(
  PIC_newdata$PICpercellpg <2  ~ "naked_bouyant",
  PIC_newdata$PICpercellpg >2 & PIC_newdata$PICpercellpg < 4 ~ "naked/calcified uncertain",
  PIC_newdata$PICpercellpg >4 & PIC_newdata$PICpercellpg < 10 ~ "moderately calcified",
  PIC_newdata$PICpercellpg >10 ~ "strongly calcified", 
  TRUE ~ as.character(PIC_newdata$PICpercellpg)
)
PIC_newdata$group2 <- factor (PIC_newdata$group2,levels= c("naked_bouyant", "naked/calcified uncertain",
                                                       "moderately calcified", "strongly calcified"),
                                                       labels = c("naked", "naked/calcified uncertain",
                                                                  "moderately calcified", "strongly calcified"))
ggplotly(ggplot(data=PIC_newdata, aes(x=group2, y=PICpercellpg)) + geom_boxplot()+geom_point(size=2)
         +theme_Publication())

#a. for host
PIC_newdata$SinkVel.pred <- predict(PIC_reg, data.frame(PIC_newdata))
PIC_newdata_reg <- lm(SinkVel.pred~PICpercellpg, data=PIC_newdata) 
coef(PIC_newdata_reg)
 (Intercept) PICpercellpg 
  0.01800852   0.01774764 
#same coef as PIC_reg
#> coef(PIC_newdata_reg)
#(Intercept) PICpercellpg 
#0.01800852   0.01774764 
plot(resid(PIC_newdata_reg))

ggplot(data=PIC_newdata, aes(x=PICpercellpg, y=SinkVel.pred)) +geom_point(size=2) +theme_Publication()+
  labs(y = expression("Predicted Sinking velocity"~("m"~day^-1)), x = expression("PIC"~cell^-1)) 

PIC_newdata$beta.pred <- predict(beta_reg, data.frame(PIC_newdata))
PIC_newdata$E_DS_V.pred <- predict(E_DS_V_reg, data.frame(PIC_newdata))
PIC_newdata$E_DS_HV.pred <- predict(E_DS_HV_reg, data.frame(PIC_newdata))
ggplot(data=PIC_newdata, aes(x=PICpercellpg, y=E_DS_V.pred)) +geom_point(size=5, aes(color=group2)) +
    theme_Publication() + geom_smooth() +
    scale_y_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=4),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) + annotation_logticks(sides="l") +
    labs(y = expression("viral encounters " ~ day^-1~cell^-1), x = expression("PIC"~cell^-1)) +
  theme(legend.title = element_blank())

ggplot(data=PIC_newdata, aes(x=PICpercellpg, y=E_DS_HV.pred)) +geom_point(size=5, aes(color=group2)) +
    theme_Publication() + geom_smooth() +
    scale_y_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=4),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) + annotation_logticks(sides="l") +
    labs(y = expression("viral encounters " ~ cm^-3~day^-1), x = expression("PIC"~cell^-1)) +
  theme(legend.title = element_blank())

PICbeta_new <- ggplot(data=PIC_newdata, aes(x=PICpercellpg, y=beta.pred)) +
  geom_point(size=5, aes(color=PICpercellpg))+
  scale_colour_gradient(name="PIC", guide=guide_colorbar(direction = "vertical", barheight=10))+
  theme_Publication() + 
  scale_y_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=4),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) + annotation_logticks(sides="l") +
  labs(y = expression(beta~("Predicted Encounters"~cm^3~day^-1)), x = expression("PIC"~cell^-1))+
  theme(legend.position = "right")
PICbeta_new

#b. for liths
PIC_newdata$perlithpg.pred <- predict(perlith_reg, data.frame(PIC_newdata))
PIC_newdata$SinkVel.pred.lith <- predict(sinkvel_lith_reg, data.frame(PIC_newdata))
sinkvel_lith_reg.pred <- lm(SinkVel.pred.lith~PICpercellpg, data=PIC_newdata) 
coef(sinkvel_lith_reg.pred)
 (Intercept) PICpercellpg 
  0.01672753   0.01115169 
#same coef as sinkvel_lith_reg
#> coef(sinkvel_lith_reg.pred)
#(Intercept) PICpercellpg 
# 0.01672753   0.01115169 
plot(resid(sinkvel_lith_reg.pred))

ggplot(data=PIC_newdata, aes(x=perlithpg.pred, y=SinkVel.pred.lith)) +geom_point(size=2) +theme_Publication()+
  labs(y = expression("Predicted Sinking velocity of Liths"~("m"~day^-1)), x = expression("PIC"~lith^-1)) 

PIC_newdata$beta.pred.lith <- predict(beta_lith_reg, data.frame(PIC_newdata))
PIC_newdata$E_DS_V.pred.lith <- predict(Elith_DS_HV_reg, data.frame(PIC_newdata))
PIC_newdata$E_DS_HV.pred.lith <- predict(Elith_DS_HV_reg, data.frame(PIC_newdata))
ggplot(data=PIC_newdata, aes(x=PICpercellpg, y=E_DS_V.pred.lith)) +geom_point(size=5, aes(color=group2)) +
    theme_Publication() + geom_smooth() +
    scale_y_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=4),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) + annotation_logticks(sides="l") +
    labs(y = expression("viral encounters " ~ day^-1~cell^-1), x = expression("PIC"~lith^-1)) +
  theme(legend.title = element_blank())

ggplot(data=PIC_newdata, aes(x=PICpercellpg, y=E_DS_HV.pred.lith)) +geom_point(size=5, aes(color=group2)) +
    theme_Publication() + geom_smooth() +
    scale_y_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=4),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) + annotation_logticks(sides="l") +
    labs(y = expression("viral encounters " ~ cm^-3~day^-1), x = expression("PIC"~lith^-1)) +
  theme(legend.title = element_blank())

PICbeta_new.lith <- ggplot(data=PIC_newdata, aes(x=perlithpg.pred, y=beta.pred.lith)) +
  geom_point(size=5, aes(color=PICpercellpg))+
  scale_colour_gradient(name="PIC", guide=guide_colorbar(direction = "vertical", barheight=10))+
  theme_Publication() + 
  scale_y_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=4),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) + annotation_logticks(sides="l") +
  labs(y = expression(beta~("Predicted Encounters of lith " ~cm^3~day^-1)), x = expression("PIC"~lith^-1))+
  theme(legend.position = "right")
PICbeta_new.lith

#summaries
summary_DS_newdata_bygroup2 <- ddply(PIC_newdata, .(group2), summarize,  PICpercellpg=mean(PICpercellpg), SinkVel.pred=mean(SinkVel.pred),beta.pred= mean (beta.pred), E_DS_V.pred= mean(E_DS_V.pred), E_DS_HV.pred=mean(E_DS_HV.pred))
summary_DS_bygroup.pred <- ddply(PIC_newdata, .(group2), summarize,  PICpercellpg=mean(PICpercellpg), 
                            perlithpg.pred = mean(perlithpg.pred), SinkVel.pred=mean(SinkVel.pred),
                            beta.pred= mean (beta.pred), E_DS_V.pred= mean(E_DS_V.pred), 
                            E_DS_HV.pred=mean(E_DS_HV.pred), 
                            SinkVel.pred.lith=mean(SinkVel.pred.lith),beta.pred.lith= mean (beta.pred.lith),
                            E_DS_V.pred.lith= mean(E_DS_V.pred.lith), E_DS_HV.pred.lith=mean(E_DS_HV.pred.lith))
summary_DS_bygroup.pred
write.xlsx(summary_DS_bygroup.pred, file = "Postdoc-R/Exported Tables/summary_DS_bygroup.pred.xlsx")
cannot create file 'Postdoc-R/Exported Tables/summary_DS_bygroup.pred.xlsx', reason 'No such file or directory'

turbulence

#TURBULENCE
#disrate is cm2/s3
#make data frame
disrate <- rep_len (c (1 %o% 10^(seq(-8,-2, 0.5))), length.out=26)
calc <- rep_len(c("calcified"), length.out=13)
naked <- rep_len(c("naked"), length.out=13)
lith <- rep_len(c("lith"), length.out=13)
group <- c(calc, naked, lith)
turb <- as.data.frame(cbind(disrate, group))
number of rows of result is not a multiple of vector length (arg 1)
turb$rad <- case_when(
    turb$group =="naked" ~ 1.8E-6,
    turb$group =="calcified" ~ 2.3E-6,
    turb$group =="lith" ~ 2E-6,
    TRUE ~ as.numeric(turb$group)
)
#turb <- mutate(turb, rad = ifelse(group == "naked" ,  1.8E-6,  2.3E-6)) #in m
turb$disrate <- as.numeric(as.character(turb$disrate))
turb$Kol <- ((v^3/turb$disrate)^0.25)*100 #Kolmogorov length scale in cm
#everything is below 1 cm, use eqn 2 in TK 
turb$beta_d <- (4.2*pi*((turb$disrate/(v*100^2))^0.5)*(((turb$rad+Rehv)*100)^3))*86400 
turb$beta_Heidi <- (0.42*pi*((turb$disrate/(v*100^2))^0.5)*(((turb$rad+Rehv)*100)^3))*86400
#check encounters
#use TK, in cm3 s
turb$E_turb_HV <- (turb$beta_d*hostnum*virnum) #E calculated with Virus and Host (10:1 MOI)
turb$E_turb_V <- (turb$beta_d*virnum) #E calculated with virus only
#breaks <- 10^(-10:10)
#minor_breaks <- rep(1:9, 21)*(10^rep(-10:10, each=9))
ggplot(data = turb, aes(x = disrate, y = beta_d, color=group)) + geom_point(size =5) +
  scale_y_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=4),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) +
  scale_x_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=4),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) +
  annotation_logticks() +
  theme_Publication() +
  labs(y = expression(beta~("predicted encounters " ~cm^3~day^-1)), 
       x = expression("dissipation rate "~(m^2~s^-3))) +
   theme(legend.title = element_blank())

  
library(scales)

Attaching package: <U+393C><U+3E31>scales<U+393C><U+3E32>

The following object is masked from <U+393C><U+3E31>package:readr<U+393C><U+3E32>:

    col_factor
ggplot(data = turb, aes(x = disrate, y = E_turb_V, color=group)) + geom_point(size =5) +
   scale_y_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=4),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) +
  scale_x_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=8),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) +
  annotation_logticks()+
  theme_Publication()+
  labs(y = expression("viral encounters " ~ day^-1~cell^-1), x = expression("dissipation rate "~(m^2~s^-3))) +
  theme(legend.title = element_blank())

ggplot(data = turb, aes(x = disrate, y = E_turb_HV, color=group)) + geom_point(size =5) +
   scale_y_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=4),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) +
  scale_x_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=7),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) +
  annotation_logticks()+
  theme_Publication()+
  labs(y = expression("viral encounters " ~ cm^-3~day^-1),x = expression("dissipation rate "~(m^2~s^-3))) +
  theme(legend.title = element_blank())

add beta kernels and plot

#extract mean betas from PIC_newdata
beta_DS <- summarySE (PIC_newdata, measurevar = "beta.pred", groupvars = c("group", "group2"))
lith_DS <-summarySE (PIC_newdata, measurevar = "beta.pred.lith", groupvars = c("group", "group2"))
lith_DS$group1 <- lith_DS$group
lith_DS$group <- "lith"
#separate data frames for host and liths
all <- Reduce(function(x,y) merge(x,y,by="group",all=TRUE) ,
              list(BM, beta_DS, turb %>% filter(group %in% c("naked", "calcified"))))
all.liths  <- Reduce(function(x,y) merge(x,y,by="group",all=TRUE) ,
                     list(lith_DS, turb %>% filter(group %in% c("lith"))))
#beta_d.x=BM, beta.pred=DS, betapred.lith= beta.pred.lith, beta_d.y=turb
#rename beta.pred to beta_pred so I can use grep. 
#all <- rename (all, c("beta_d.x" = "beta_BM", "beta.pred" = "beta_DS", "beta_d.y" = "beta_turb"))
library(data.table)
data.table 1.11.8  Latest news: r-datatable.com

Attaching package: <U+393C><U+3E31>data.table<U+393C><U+3E32>

The following objects are masked from <U+393C><U+3E31>package:dplyr<U+393C><U+3E32>:

    between, first, last
NT = data.table(all, key="group2")
allbetas = NT[, list(group=group, disrate=disrate, beta_BM=beta_d.x, beta_DS=beta.pred, beta_turb = beta_d.y, 
                     beta_BM_DS =beta_d.x + beta.pred,
                     beta_DS_turb = beta.pred + beta_d.y,
                     beta_BM_turb = beta_d.x + beta_d.y,
                     beta_all = beta_d.x + beta_d.y + beta.pred), 
              by=c("group2")]
NT2 <- data.table(all.liths, key = "group2")
allbetas.lith = NT2[, list(group=group, group1=group1, disrate=disrate, beta_DS.lith=beta.pred.lith, 
                          beta_turb.lith = beta_d, 
                     beta_DS_turb.lith =beta.pred.lith + beta_d), 
                     by=c("group2")]
ggplot(allbetas, aes(disrate, y = value, color=group2)) + 
    geom_line(aes(y = beta_DS_turb, linetype = "DS+turb"), size=1) + 
    geom_line(aes(y = beta_all, linetype = "BM+DS+turb"), size=1)+
    geom_line(aes(y = beta_turb, linetype = "turb"), size=1)+
    geom_line(data = allbetas.lith, aes(y= beta_DS_turb.lith, linetype="DS+turb.lith")) +
    scale_y_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=4),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) +
    scale_x_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=7),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) +
    annotation_logticks()+
    theme_Publication() +
    theme(legend.title = element_blank(), legend.key.width=unit(2,"cm"))+
    guides(linetype=guide_legend(nrow  =4), colour=guide_legend(nrow=4,byrow=TRUE)) 

ggplot(allbetas, aes(disrate, y = value, color=group2)) + 
  geom_line(aes(y = beta_DS_turb, linetype = "DS+turb"), size=1) + 
  geom_line(data = allbetas.lith, aes(y= beta_DS_turb.lith, linetype="DS+turb.lith")) + 
  scale_y_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=4),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) +
  scale_x_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=7),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) +
  annotation_logticks()+
  theme_Publication() +
  theme(legend.title = element_blank(), legend.key.width=unit(2,"cm"))+
  guides(linetype=guide_legend(nrow  =4), colour=guide_legend(nrow=4,byrow=TRUE)) 

#encounters
#melt data
allbetas.melt <- melt (allbetas, id.vars = c("group2", "group", "disrate"), value.name = "beta_d", 
                       variable.name = "betakernel")
allbetas.melt$E_V <- allbetas.melt$beta_d*virnum
allbetas.melt$E_HV <- allbetas.melt$beta_d*virnum*hostnum
allbetas.melt.lith <- melt (allbetas.lith, id.vars = c("group2", "group1", "group", "disrate"), 
                            value.name = "beta_d", variable.name = "betakernel")
allbetas.melt.lith$E_V <- allbetas.melt.lith$beta_d*virnum
allbetas.melt.lith$E_HV <- allbetas.melt.lith$beta_d*virnum*hostnum
ggplot(allbetas.melt, aes(disrate, y = E_V, color=group2)) + 
  geom_line(size=1)+
  scale_y_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=4),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) +
  scale_x_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=7),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) +
  annotation_logticks() + facet_grid(~betakernel)

#subset data
graph1 <- subset(allbetas.melt, betakernel %in% c ("beta_BM", "beta_DS", "beta_BM_DS"))
graph2 <- subset(allbetas.melt, betakernel %in% c ("beta_turb", "beta_DS_turb", "beta_BM_turb", "beta_all"))
lith <- subset(allbetas.melt.lith, betakernel %in% c("beta_DS_turb.lith") & group1 %in% c("calcified"))
lith$maingroup <- lith$group2
lith$group2 <- as.factor(paste(lith$maingroup, lith$group, sep='-'))
ggplot(graph1, aes(group2, y = E_V, color=betakernel)) + 
  geom_jitter(size=5)+
  scale_y_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=4),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) +
  annotation_logticks(sides = "l")+
  theme_Publication() +
  labs(y = expression("viral encounters " ~ day^-1~cell^-1)) +
  theme(legend.title = element_blank())

graph1.sum <- summarySE (graph1, measurevar = "E_V", groupvars = c("betakernel", "group2"))
ggplot(graph1.sum, aes(group2, y = E_V, color=betakernel)) + 
  geom_point(size=5,  position=position_dodge(0.2))+
  scale_y_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=4),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) +
  annotation_logticks(sides = "l")+
  theme_Publication() +
  labs(y = expression("viral encounters " ~ day^-1~cell^-1)) +
  theme(legend.title = element_blank())

  
ggplot(data=allbetas.melt %>% filter(betakernel %in% c("beta_turb", "beta_all")), 
       aes(x=disrate,y = E_V, color=group2, linetype=betakernel)) + 
  geom_line(size=1, position=position_jitter(w=0.02, h=0))+
   scale_y_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=4),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) +
  scale_x_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=7),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) +
  annotation_logticks()+
  theme_Publication()+
  theme(legend.title = element_blank(), legend.key.width=unit(2,"cm"))+
  guides(linetype=guide_legend(nrow  =4), colour=guide_legend(nrow=4,byrow=TRUE)) +
  labs(y = expression("viral encounters " ~ day^-1~cell^-1), x = expression("dissipation rate "~(m^2~s^-3))) +
  theme(legend.title = element_blank())

  
ggplot(data=allbetas.melt %>% filter(betakernel %in% c("beta_all")), 
       aes(x=disrate,y = E_V, color=group2)) + 
  geom_line(size=1, position=position_jitter(w=0.02, h=0))+
  geom_line(data = lith, aes(y= E_V, color=group2)) +
   scale_y_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=2),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) +
  scale_x_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=7),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) +
  annotation_logticks()+
  theme_Publication() +
  theme(legend.title = element_blank(), legend.key.width=unit(1,"cm"))+
  labs(y = expression("viral encounters " ~day^-1~cell^-1), x = expression("dissipation rate "~(m^2~s^-3))) +
  theme(legend.title = element_blank())

ggplot(data=allbetas.melt %>% filter(betakernel %in% c("beta_all")), 
       aes(x=disrate,y = E_HV, color=group2)) + 
  geom_line(size=1, position=position_jitter(w=0.02, h=0))+
  geom_line(data = lith, aes(y= E_HV, color=group2)) +
   scale_y_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=2),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) +
  scale_x_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=7),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) +
  annotation_logticks()+
  theme_Publication() +
  theme(legend.title = element_blank(), legend.key.width=unit(1,"cm"))+
  labs(y = expression("viral encounters " ~ cm^-3~day^-1),x = expression("dissipation rate "~(m^2~s^-3))) +
  theme(legend.title = element_blank())

allbetas.melt.dropnc <- allbetas.melt [!allbetas.melt$group2 =="naked/calcified uncertain", ]
allbetas.melt.dropnc$group2 <- factor(allbetas.melt.dropnc$group2, levels = c("naked", "moderately calcified", "moderately calcified-lith", "strongly calcified", "strongly calcified-lith"))
allbetas.melt.dropnc <- allbetas.melt.dropnc%>%
  arrange(factor(group2, c("naked", "moderately calcified", "moderately calcified-lith", "strongly calcified", "strongly calcified-lith")))
ggplot(data=allbetas.melt.dropnc %>% filter(betakernel %in% c("beta_all")), 
       aes(x=disrate,y = E_V, color=group2)) + 
    geom_line(size=1, position=position_jitter(w=0.02, h=0))+
    geom_line(data = lith, aes(y= E_V, color=group2)) +
    scale_y_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=2),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) +
    scale_x_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=7),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) +
    annotation_logticks()+
    theme_Publication() +
    theme(legend.title = element_blank(), legend.key.width=unit(1,"cm"))+
  labs(y = expression("viral encounters " ~day^-1~cell^-1), x = expression("dissipation rate "~(m^2~s^-3))) +
    theme(legend.title = element_blank())+ guides(linetype=guide_legend(nrow  =4), colour=guide_legend(nrow=4,byrow=TRUE)) 

write.xlsx(allbetas.melt.dropnc, file = "Postdoc-R/Exported Tables/allbetas.xlsx")
cannot create file 'Postdoc-R/Exported Tables/allbetas.xlsx', reason 'No such file or directory'

for saving just the R file

require (knitr)
Loading required package: knitr
purl(input = "D:/R program/Postdoc-R/R Notebook/Dec 2018/beta kernel 181204.Rmd") #output file will be on the main R directory and saved with the same file name


processing file: D:/R program/Postdoc-R/R Notebook/Dec 2018/beta kernel 181204.Rmd

  |                                                                       
  |                                                                 |   0%
  |                                                                       
  |...                                                              |   4%
  |                                                                       
  |......                                                           |   9%
  |                                                                       
  |........                                                         |  13%
  |                                                                       
  |...........                                                      |  17%
  |                                                                       
  |..............                                                   |  22%
  |                                                                       
  |.................                                                |  26%
  |                                                                       
  |....................                                             |  30%
  |                                                                       
  |.......................                                          |  35%
  |                                                                       
  |.........................                                        |  39%
  |                                                                       
  |............................                                     |  43%
  |                                                                       
  |...............................                                  |  48%
  |                                                                       
  |..................................                               |  52%
  |                                                                       
  |.....................................                            |  57%
  |                                                                       
  |........................................                         |  61%
  |                                                                       
  |..........................................                       |  65%
  |                                                                       
  |.............................................                    |  70%
  |                                                                       
  |................................................                 |  74%
  |                                                                       
  |...................................................              |  78%
  |                                                                       
  |......................................................           |  83%
  |                                                                       
  |.........................................................        |  87%
  |                                                                       
  |...........................................................      |  91%
  |                                                                       
  |..............................................................   |  96%
  |                                                                       
  |.................................................................| 100%
output file: beta kernel 181204.R
[1] "beta kernel 181204.R"
LS0tDQp0aXRsZTogImJldGEga2VybmVsIGZpbmFsIG5vdGVib29rIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KVGhpcyBpcyBhbiBbUiBNYXJrZG93bl0oaHR0cDovL3JtYXJrZG93bi5yc3R1ZGlvLmNvbSkgTm90ZWJvb2suIFdoZW4geW91IGV4ZWN1dGUgY29kZSB3aXRoaW4gdGhlIG5vdGVib29rLCB0aGUgcmVzdWx0cyBhcHBlYXIgYmVuZWF0aCB0aGUgY29kZS4gDQoNClRyeSBleGVjdXRpbmcgdGhpcyBjaHVuayBieSBjbGlja2luZyB0aGUgKlJ1biogYnV0dG9uIHdpdGhpbiB0aGUgY2h1bmsgb3IgYnkgcGxhY2luZyB5b3VyIGN1cnNvciBpbnNpZGUgaXQgYW5kIHByZXNzaW5nICpDdHJsK1NoaWZ0K0VudGVyKi4gDQoNCkFkZCBhIG5ldyBjaHVuayBieSBjbGlja2luZyB0aGUgKkluc2VydCBDaHVuayogYnV0dG9uIG9uIHRoZSB0b29sYmFyIG9yIGJ5IHByZXNzaW5nICpDdHJsK0FsdCtJKi4NCg0KV2hlbiB5b3Ugc2F2ZSB0aGUgbm90ZWJvb2ssIGFuIEhUTUwgZmlsZSBjb250YWluaW5nIHRoZSBjb2RlIGFuZCBvdXRwdXQgd2lsbCBiZSBzYXZlZCBhbG9uZ3NpZGUgaXQgKGNsaWNrIHRoZSAqUHJldmlldyogYnV0dG9uIG9yIHByZXNzICpDdHJsK1NoaWZ0K0sqIHRvIHByZXZpZXcgdGhlIEhUTUwgZmlsZSkuDQoNClRoZSBwcmV2aWV3IHNob3dzIHlvdSBhIHJlbmRlcmVkIEhUTUwgY29weSBvZiB0aGUgY29udGVudHMgb2YgdGhlIGVkaXRvci4gQ29uc2VxdWVudGx5LCB1bmxpa2UgKktuaXQqLCAqUHJldmlldyogZG9lcyBub3QgcnVuIGFueSBSIGNvZGUgY2h1bmtzLiBJbnN0ZWFkLCB0aGUgb3V0cHV0IG9mIHRoZSBjaHVuayB3aGVuIGl0IHdhcyBsYXN0IHJ1biBpbiB0aGUgZWRpdG9yIGlzIGRpc3BsYXllZC4NCg0KYGBge3J9DQpzZXR3ZCgiRDovUiBwcm9ncmFtIikNCiN2YWx1ZXMgbmVlZGVkIA0KDQpLPSAxLjM4MDY0ODUyKigxMCleLTIzICNtMiBrZy8gczIgSyBib2x0em1hbm4gY29uc3RhbnQNCm11PSAxLjEyNiooMTApXi0zICNrZy9tIHMgZHluYW1pYyB2aXNjb3NpdHkgaW4gMThDDQp2PSAxLjA5OSooMTApXi02ICNtMi9zIGtpbmVtYXRpYyB2aXNjb3NpdHkgaW4gMThDDQpSZWhfY2FsYz0gMi4zRS02ICNpbiBtIHJhZGl1cyBFaHV4DQpSZWhfbmFrZWQ9IDEuOEUtNiAjaW4gbSByYWRpdXMgRWh1eA0KUmVodj0gOTAqKDEwKV4tOSAjaW4gbSByYWRpdXMgdmlydXMNClRlbXAgPSAxOCsyNzMuMTUgI3RlbXAgaW4ga2VsdmluLCBoZXJlIGFzc3VtaW5nIDE4Qw0KRGVuX09jTSA9IDEuMDUgI2cvY20zIGRlbnNpdHkgb3JnYW5pYyBjZWxsIG1hdHRlcg0KRGVuX0NIMk89IDEuMDI1ICNnL2NtMyBkZW5zaXR5IHNlYXdhdGVyIGF0IDE4Qw0KaG9zdG51bSA8LSAoMTApXjMNCnZpcm51bSA8LSBob3N0bnVtKjUNCg0KcmVxdWlyZSAoZ2dwbG90MikNCnJlcXVpcmUocGxvdGx5KQ0KcmVxdWlyZShncmlkKQ0KcmVxdWlyZShnZ3RoZW1lcykNCnJlcXVpcmUgKGRwbHlyKQ0KcmVxdWlyZShwbHlyKQ0Kc291cmNlICgidGhlbWVfUHVibGljYXRpb24uUiIpDQpzb3VyY2UoInJlc2l6ZXdpbi5SIikNCiNyZXNpemUud2luKDEyLDkpDQpncmlkLm5ld3BhZ2UoKQ0KDQpgYGANCg0KZm9yIEJyb3duaWFuIG1vdGlvbg0KDQpgYGB7cn0NCiNCcm93bmlhbiBtb3Rpb24gKEJNKQ0KIzEuIG1ha2UgYSBkYXRhIGZyYW1lDQpCTSA8LSBkYXRhLmZyYW1lIChncm91cD0gYygibmFrZWQiLCAiY2FsY2lmaWVkIiksIHJhZD0gYygxLjhFLTYsIDIuM0UtNikpIA0KDQojMi4gY2FsY3VsYXRlIGJldGEgKGJldGEpDQpCTSRiZXRhX3MgPC0gKDIqKEsqKDEwKV40KSpUZW1wKigoKEJNJHJhZCtSZWh2KSoxMDApXjIpKS8oKDMqbXUqMTApKihCTSRyYWQqUmVodioxZTQpKSAjbTMvcw0KQk0kYmV0YV9kIDwtIEJNJGJldGFfcyo4NjQwMCAjdG8gY20zL2RheQ0KDQojIGdvIGJhY2sgdG8gdGhpcyBsYXRlcg0KIzMuIGNhbGN1bGF0ZSBlbmNvdW50ZXJzIChFKQ0KQk0kRSA8LSBCTSRiZXRhX2QqaG9zdG51bQ0KQk0kRV9IViA8LSBCTSRiZXRhX2QqdmlybnVtKmhvc3RudW0NCg0KQk0NCmBgYA0KDQpEaWZmZXJlbnRpYWwgc2V0dGxpbmcgKERTKQ0KDQpgYGB7cn0NCiNEaWZmZXJlbnRpYWwgc2V0dGxpbmcgKERTKQ0KIzEuIHJlYWQgaW4gUElDIGRhdGENCmxpYnJhcnkocmVhZHIpICNhbHdheXMgdXNlIHJlYWRyIG5vdCBiYXNlUg0KDQpzZXR3ZCgiRDovUiBwcm9ncmFtIikNClBJQyA8LSByZWFkX2NzdigiUG9zdGRvYy1SL0NTViBGaWxlcy9QSUMuY3N2IikNCg0KUElDJFN0cmFpbiA8LSBhcy5mYWN0b3IoUElDJFN0cmFpbikNClBJQyRSZXBsaWNhdGUgPC0gYXMuZmFjdG9yKFBJQyRSZXBsaWNhdGUpDQoNCiNjZXJ0YWluIGNoYW5nZXMgaW4gZGF0YS50YWJsZSBBUEkgbWFkZSBjYWxjdWxhdGluZyBpbnNpZGUgdGhlIGxpc3QgZGF0YS50YWJsZSB0byBub3Qgd29yaw0KDQojMi4gY2FsY3VsYXRlIFBJQw0KUElDJFBJQyA8LSBQSUMkVEMtUElDJEFDDQpQSUMkUElDcGVyY2VsbCA8LSAoUElDJFBJQy9QSUMkQ2VsbGNvdW50KSooMTApXi0zI2luIGcNClBJQyRQSUNwZXJjZWxscGcgPC0gUElDJFBJQ3BlcmNlbGwqMWUxMg0KUElDJFRDcGcgPC0gKFBJQyRUQy9QSUMkQ2VsbGNvdW50KSooMTApXi0zKjFlMTIgI3doYXQgaWYgdG90YWwgY2FyYm9uIGlzIHVzZWQgZm9yIGNhbGN1bGF0aW5nIGRlbnNpdHkNCg0KZ2dwbG90bHkoZ2dwbG90KGRhdGE9UElDLCBhZXMoeD1TdHJhaW4sIHk9UElDcGVyY2VsbHBnKSkgKyBnZW9tX2JveHBsb3QoKStnZW9tX3BvaW50KHNpemU9MikgK3RoZW1lX1B1YmxpY2F0aW9uKCkpDQpnZ3Bsb3RseShnZ3Bsb3QoZGF0YT1QSUMsIGFlcyh4PVN0cmFpbiwgeT1UQ3BnKSkgKyBnZW9tX2JveHBsb3QoKStnZW9tX3BvaW50KHNpemU9MikgK3RoZW1lX1B1YmxpY2F0aW9uKCkpDQoNCmBgYA0KDQpgYGB7cn0NCg0KIzMuIGNhbGN1bGF0ZSBkZW5zaXR5IG9mIGNlbGxzIChkZW4pDQpQSUMgPC0gbXV0YXRlKFBJQywgZ3JvdXAgPSBpZmVsc2UoUElDcGVyY2VsbHBnIDwgNCAsICJuYWtlZCIsICJjYWxjaWZpZWQiKSkNCg0KZ2dwbG90bHkoZ2dwbG90KGRhdGE9UElDLCBhZXMoeD1ncm91cCwgeT1QSUNwZXJjZWxscGcpKSArIGdlb21fYm94cGxvdCgpK2dlb21fcG9pbnQoc2l6ZT0yLCBhZXMoY29sb3I9U3RyYWluKSkrDQogICAgICAgICAgIHRoZW1lX1B1YmxpY2F0aW9uKCkpDQoNClBJQyA8LSBtdXRhdGUoUElDLCByYWQgPSBpZmVsc2UoZ3JvdXAgPT0gIm5ha2VkIiAsICAxLjhFLTYsICAyLjNFLTYpKSAjaW4gbQ0KDQpQSUMkdm9sdW1lIDwtICg0LzMpKnBpKihQSUMkcmFkKjEwMCleMyAjaW4gY20zDQpQSUMkRGVuX2NlbGwyIDwtIChQSUMkVENwZyoxZS0xMikvUElDJHZvbHVtZSAjZy9jbTMsIGlmIFRDIGlzIHVzZWQgZGVuc2l0eSwgdG90YWwgZGVuc2l0eSAoYmVsb3cpIGJlY29tZXMgcmVhbGx5IGJpZyAoaS5lLiwgbWF4IDIgZy9jbTMgd2hpY2ggaXMgbm90IHJlYXNvbmFibGUpDQoNClBJQyREZW5fY2VsbCA8LSBQSUMkUElDcGVyY2VsbC9QSUMkdm9sdW1lICNnL2NtMw0KUElDJERlbl9jZWxsdG90YWwgPC0gUElDJERlbl9jZWxsK0Rlbl9PY00NCg0KZ2dwbG90bHkoZ2dwbG90KGRhdGE9UElDLCBhZXMoeD1TdHJhaW4sIHk9RGVuX2NlbGx0b3RhbCwgY29sb3I9Z3JvdXApKSArIGdlb21fYm94cGxvdCgpK2dlb21fcG9pbnQoc2l6ZT0yKSANCiAgICAgICAgICt0aGVtZV9QdWJsaWNhdGlvbigpKQ0KDQojc29tZSBzdHJhaW5zIHRoYXQgYXJlICJuYWtlZCIgaGF2ZSBQSUM8Mi4gSSBjaG9zZSB0byBpZ25vcmUgdGhpcyBzaW5jZSBpbiB0aGUgbG0gbW9kZWwgSSBkbyBub3QgdXNlDQojc3RyYWluIGFzIGEgZmFjdG9yLCByYXRoZXIgZGF0YSBpcyB0cmVhdGVkIGFzIGEgd2hvbGUgKGUuZy4sIG5vIGdyb3VwaW5nKQ0KDQojNC4gY2FsY3VsYXRlIHNpbmtpbmcgdmVsb2NpdHkgb2YgY2VsbHMNClBJQyRTaW5rVmVsIDwtICgoMiooKFBJQyRyYWQqMTAwKV4yKSooOTgxKSooUElDJERlbl9jZWxsdG90YWwtRGVuX0NIMk8pKS8oOSoobXUqMTApKSkqODY0ICNtZXRlciBwZXIgZGF5DQoNCiNnIGlzIGNvbnZlcnRlZCB0byBwZXIgZGF5LCA4NjQgaXMgdGhlIG9uZSB0aGF0IGNvbnZlcnRzIGNtL3MgdG8gbS9kYXkNCg0KI3Bsb3Qgc2lua2luZyB2ZWxvY2l0eSB2cyBjYWxjaWZpY2F0aW9uDQoNCmdncGxvdChkYXRhPVBJQywgYWVzKHg9UElDcGVyY2VsbHBnLCB5PVNpbmtWZWwsIGNvbG9yPVN0cmFpbiwgc2hhcGU9Z3JvdXApKSArIGdlb21fcG9pbnQoc2l6ZT01KSt0aGVtZV9QdWJsaWNhdGlvbigpKw0KICAgIGxhYnMoeSA9IGV4cHJlc3Npb24oIlNpbmtpbmcgdmVsb2NpdHkifigibSJ+ZGF5Xi0xKSksIHggPSBleHByZXNzaW9uKCJQSUMifmNlbGxeLTEpKSArDQogICAgc2NhbGVfeV9sb2cxMCgNCiAgICAgICAgYnJlYWtzID0gc2NhbGVzOjp0cmFuc19icmVha3MoImxvZzEwIiwgZnVuY3Rpb24oeCkgMTBeeCwgbj0yKSwNCiAgICAgICAgbGFiZWxzID0gc2NhbGVzOjp0cmFuc19mb3JtYXQoImxvZzEwIiwgc2NhbGVzOjptYXRoX2Zvcm1hdCgxMF4ueCkpKSArIGFubm90YXRpb25fbG9ndGlja3Moc2lkZXM9ImwiKQ0KDQojNS4gY2FsY3VsYXRlIHNpbmt2ZWwgb2YgdmlydXNlcw0KDQpEZW5fdmlydXMgPC0gMS4wOSAjZGF0YSBmcm9tIEJlbiBELiBmcmVzaCBFaFYtMjA3IGRlbnNpdHkuIG9sZCBkZW5zaXR5IG9mIEVoVi0yMDcgaXMgMS4xOQ0KRWh2X1NpbmtWZWwgPC0gKCgyKigoUmVodioxMDApXjIpKig5ODEpKihEZW5fdmlydXMtRGVuX0NIMk8pKS8oOSoobXUqMTApKSkqODY0ICAjZXF1YWxzIHRvIDANCg0KIzYuIGNhbGN1bGF0ZSBiZXRhIGtlcm5lbHMNClBJQyRiZXRhX3MgPC0gcGkqKCgoUElDJHJhZCtSZWh2KSoxMDApXjIpKihhYnMoKFBJQyRTaW5rVmVsLUVodl9TaW5rVmVsKS84NjQpKSAjaW4gZW5jb3VudGVycyBjbTMvcw0KUElDJGJldGFfZCA8LSBQSUMkYmV0YV9zKjg2NDAwICNpbiBjbTMvZGF5DQoNClNpbmt2ZWxiZXRhLnBsb3Q8LSBnZ3Bsb3QoZGF0YT1QSUMsIGFlcyh4PVNpbmtWZWwsIHk9YmV0YV9kLCBjb2xvcj1TdHJhaW4sIHNoYXBlPWdyb3VwKSkgKyBnZW9tX3BvaW50KHNpemU9NSkrDQogIHRoZW1lX1B1YmxpY2F0aW9uKCkrDQogIGxhYnMoeCA9IGV4cHJlc3Npb24oIlNpbmtpbmcgdmVsb2NpdHkifigibSJ+ZGF5Xi0xKSksIHkgPSBleHByZXNzaW9uKGJldGF+KCJFbmNvdW50ZXJzIiB+IGNtXjN+ZGF5Xi0xKSkpICsNCiBzY2FsZV95X2xvZzEwKA0KICAgICAgICBicmVha3MgPSBzY2FsZXM6OnRyYW5zX2JyZWFrcygibG9nMTAiLCBmdW5jdGlvbih4KSAxMF54LCBuPTIpLA0KICAgICAgICBsYWJlbHMgPSBzY2FsZXM6OnRyYW5zX2Zvcm1hdCgibG9nMTAiLCBzY2FsZXM6Om1hdGhfZm9ybWF0KDEwXi54KSkpICsgYW5ub3RhdGlvbl9sb2d0aWNrcyhzaWRlcz0ibCIpDQoNClNpbmt2ZWxiZXRhLnBsb3QgI2NoYW5nZSB0aWNrcw0KDQojZ2dwbG90bHkoU2lua3ZlbGJldGEucGxvdCkNCg0KZ2dwbG90bHkoZ2dwbG90KGRhdGE9UElDLCBhZXMoeD1TdHJhaW4sIHk9U2lua1ZlbCkpICsgZ2VvbV9ib3hwbG90KCkrdGhlbWVfUHVibGljYXRpb24oKSkNCg0KZ2dwbG90KGRhdGE9UElDLCBhZXMoeD1QSUNwZXJjZWxscGcsIHk9YmV0YV9kLCBjb2xvcj1TdHJhaW4pKSArIGdlb21fcG9pbnQoc2l6ZT01KSt0aGVtZV9QdWJsaWNhdGlvbigpKw0KICBsYWJzKHkgPSBleHByZXNzaW9uKGJldGF+KCJFbmNvdW50ZXJzIn5jbV4zfmRheV4tMSkpLCB4ID0gZXhwcmVzc2lvbigiUElDIn5jZWxsXi0xKSkgICsNCnNjYWxlX3lfbG9nMTAoDQogICAgICAgIGJyZWFrcyA9IHNjYWxlczo6dHJhbnNfYnJlYWtzKCJsb2cxMCIsIGZ1bmN0aW9uKHgpIDEwXngsIG49MiksDQogICAgICAgIGxhYmVscyA9IHNjYWxlczo6dHJhbnNfZm9ybWF0KCJsb2cxMCIsIHNjYWxlczo6bWF0aF9mb3JtYXQoMTBeLngpKSkgKyBhbm5vdGF0aW9uX2xvZ3RpY2tzKHNpZGVzPSJsIikNCg0KYGBgDQoNCmBgYHtyfQ0KIzcuIGNhbGN1bGF0ZSBiZXRhIGFuZCBlbmNvdW50ZXJzDQojYmV0YSBhcmUgaW4gY2VsbHMgY20zLyBkYXkgdGhlbiBlbmNvdW50ZXJzIGFyZSB0byBjZWxscy9jbTMgZGF5DQpQSUMkRV9EU19IViA8LSAoUElDJGJldGFfZCp2aXJudW0qaG9zdG51bSkgICNFIGNhbGN1bGF0ZWQgd2l0aCBWaXJ1cyBhbmQgSG9zdCAoMTA6MSBNT0kpDQpQSUMkRV9EU19WIDwtIChQSUMkYmV0YV9kKnZpcm51bSkgI0UgY2FsY3VsYXRlZCB3aXRoIFZpcnVzDQoNCiM4LiBjYWxjdWxhdGUgZm9yIGxpdGggcGFyYW1ldGVycw0KDQpsaXRodm9sIDwtIDMqMWUtMTIgI2luIGNtMywgZnJvbSBDSidzIHBhcGVyDQpQSUMkcGVybGl0aCA8LSBQSUMkUElDcGVyY2VsbC8yMCAjaW4gZywgYXNzdW1pbmcgMjAgbGl0aHMgYXR0YWNoZWQNClBJQyRwZXJsaXRocGcgPC0gUElDJHBlcmxpdGgqMWUxMiAjaW4gcGcNClBJQyREZW5saXRoIDwtIChQSUMkcGVybGl0aC9saXRodm9sKSArIERlbl9PY00gI2luIGcvY20zLCB3aXRoIG9yZ2FuaWMgbWF0dGVyIGF0dGFjaGVkDQpQSUMkRGVubGl0aF9ub09DTSA8LSAoUElDJHBlcmxpdGgvbGl0aHZvbCkgI2luIGcvY20zLCB3aXRoIG9yZ2FuaWMgbWF0dGVyIGF0dGFjaGVkDQpyYWRfbGl0aCA8LSAyRS02ICNpbiBtIHJhZGl1cw0KDQpQSUMkU2lua1ZlbF9saXRoIDwtICgoMiooKHJhZF9saXRoKjEwMCleMikqKDk4MSkqKFBJQyREZW5saXRoLURlbl9DSDJPKSkvKDkqKG11KjEwKSkpKjg2NCAjbWV0ZXIgcGVyIGRheQ0KUElDJGJldGFfc19saXRoIDwtIHBpKigoKHJhZF9saXRoK1JlaHYpKjEwMCleMikqKGFicygoUElDJFNpbmtWZWxfbGl0aC1FaHZfU2lua1ZlbCkvODY0KSkgI2luIGVuY291bnRlcnMgY20zL3MNClBJQyRiZXRhX2RfbGl0aCA8LSBQSUMkYmV0YV9zX2xpdGgqODY0MDAgI2luIGNtMy9kYXkNCg0KZ2dwbG90KGRhdGE9UElDLCBhZXMoeD1wZXJsaXRocGcsIHk9U2lua1ZlbF9saXRoLCBjb2xvcj1TdHJhaW4sIHNoYXBlPWdyb3VwKSkgKyBnZW9tX3BvaW50KHNpemU9NSkrdGhlbWVfUHVibGljYXRpb24oKSsNCiAgbGFicyh5ID0gZXhwcmVzc2lvbigiU2lua2luZyB2ZWxvY2l0eSJ+KCJtIn5kYXleLTEpKSwgeCA9IGV4cHJlc3Npb24oIlBJQyJ+bGl0aF4tMSkpIA0KDQpQSUMkRWxpdGhfRFNfSFYgPC0gKFBJQyRiZXRhX2RfbGl0aCp2aXJudW0qaG9zdG51bSkgICNFIGNhbGN1bGF0ZWQgd2l0aCBWaXJ1cyBhbmQgSG9zdCAoMTA6MSBNT0kpDQpQSUMkRWxpdGhfRFNfViA8LSAoUElDJGJldGFfZF9saXRoKnZpcm51bSkgI0UgY2FsY3VsYXRlZCB3aXRoIFZpcnVzDQoNCnJlcXVpcmUgKGRwbHlyKQ0KDQpQSUMkZ3JvdXAyIDwtIGNhc2Vfd2hlbigNCiAgUElDJFBJQ3BlcmNlbGxwZyA8MiAgfiAibmFrZWRfYm91eWFudCIsDQogIFBJQyRQSUNwZXJjZWxscGcgPjIgJiBQSUMkUElDcGVyY2VsbHBnIDwgNCB+ICJuYWtlZC9jYWxjaWZpZWQgdW5jZXJ0YWluIiwNCiAgUElDJFBJQ3BlcmNlbGxwZyA+NCAmIFBJQyRQSUNwZXJjZWxscGcgPCAxMCB+ICJtb2RlcmF0ZWx5IGNhbGNpZmllZCIsDQogIFBJQyRQSUNwZXJjZWxscGcgPjEwIH4gInN0cm9uZ2x5IGNhbGNpZmllZCIsIA0KICBUUlVFIH4gYXMuY2hhcmFjdGVyKFBJQyRQSUNwZXJjZWxscGcpDQopDQoNCmJyZWFrcyA8LSAxMF4oLTEwOjEwKQ0KDQpnZ3Bsb3QoZGF0YT1QSUMsIGFlcyh4PVNpbmtWZWwsIHk9RV9EU19IViwgY29sb3I9U3RyYWluLCBzaGFwZT1ncm91cCkpICsgZ2VvbV9wb2ludChzaXplPTUpK3RoZW1lX1B1YmxpY2F0aW9uKCkrDQogc2NhbGVfeV9sb2cxMCgNCiAgICAgICAgYnJlYWtzID0gc2NhbGVzOjp0cmFuc19icmVha3MoImxvZzEwIiwgZnVuY3Rpb24oeCkgMTBeeCwgbj0yKSwNCiAgICAgICAgbGFiZWxzID0gc2NhbGVzOjp0cmFuc19mb3JtYXQoImxvZzEwIiwgc2NhbGVzOjptYXRoX2Zvcm1hdCgxMF4ueCkpKSArIGFubm90YXRpb25fbG9ndGlja3Moc2lkZXM9ImwiKQ0KDQoNCmdncGxvdChkYXRhPVBJQywgYWVzKHg9U2lua1ZlbCwgeT1FX0RTX1YsIGNvbG9yPVN0cmFpbiwgc2hhcGU9Z3JvdXApKSArIGdlb21fcG9pbnQoc2l6ZT01KSt0aGVtZV9QdWJsaWNhdGlvbigpKw0KICBzY2FsZV95X2xvZzEwKA0KICAgICAgICBicmVha3MgPSBzY2FsZXM6OnRyYW5zX2JyZWFrcygibG9nMTAiLCBmdW5jdGlvbih4KSAxMF54LCBuPTIpLA0KICAgICAgICBsYWJlbHMgPSBzY2FsZXM6OnRyYW5zX2Zvcm1hdCgibG9nMTAiLCBzY2FsZXM6Om1hdGhfZm9ybWF0KDEwXi54KSkpICsgYW5ub3RhdGlvbl9sb2d0aWNrcyhzaWRlcz0ibCIpDQoNCg0KZ2dwbG90KGRhdGE9UElDLCBhZXMoeD1TaW5rVmVsX2xpdGgsIHk9RWxpdGhfRFNfViwgY29sb3I9U3RyYWluLCBzaGFwZT1ncm91cCkpICsgZ2VvbV9wb2ludChzaXplPTUpICsgDQogIHRoZW1lX1B1YmxpY2F0aW9uKCkgKyBzY2FsZV95X2xvZzEwKA0KICAgICAgICBicmVha3MgPSBzY2FsZXM6OnRyYW5zX2JyZWFrcygibG9nMTAiLCBmdW5jdGlvbih4KSAxMF54LCBuPTMpLA0KICAgICAgICBsYWJlbHMgPSBzY2FsZXM6OnRyYW5zX2Zvcm1hdCgibG9nMTAiLCBzY2FsZXM6Om1hdGhfZm9ybWF0KDEwXi54KSkpICsgYW5ub3RhdGlvbl9sb2d0aWNrcyhzaWRlcz0ibCIpDQoNCg0KDQpzdW1tYXJ5X0RTIDwtIGRkcGx5KFBJQywgLihTdHJhaW4pLCBzdW1tYXJpemUsICBQSUNwZXJjZWxscGc9bWVhbihQSUNwZXJjZWxscGcpLCBwZXJsaXRocGcgPSBtZWFuKHBlcmxpdGhwZyksIA0KICAgICAgICAgICAgICAgICAgICBEZW5fY2VsbHRvdGFsID0gbWVhbiAoRGVuX2NlbGx0b3RhbCksDQogICAgICAgICAgICAgICAgICAgIFNpbmtWZWw9bWVhbihTaW5rVmVsKSxiZXRhX2Q9bWVhbihiZXRhX2QpLCBFX0RTX1Y9IG1lYW4oRV9EU19WKSwgRV9EU19IVj1tZWFuKEVfRFNfSFYpLA0KICAgICAgICAgICAgICAgICAgICBTaW5rVmVsX2xpdGg9bWVhbiAoU2lua1ZlbF9saXRoKSwgYmV0YV9kX2xpdGg9bWVhbiAoYmV0YV9kX2xpdGgpLCBFbGl0aF9EU19IVj1tZWFuIChFbGl0aF9EU19IViksDQogICAgICAgICAgICAgICAgICAgIEVsaXRoX0RTX1Y9bWVhbiAoRWxpdGhfRFNfVikpDQoNCnN1bW1hcnlfRFNfYnlncm91cCA8LSBkZHBseShQSUMsIC4oZ3JvdXAyKSwgc3VtbWFyaXplLCAgUElDcGVyY2VsbHBnPW1lYW4oUElDcGVyY2VsbHBnKSwgcGVybGl0aHBnID0gbWVhbihwZXJsaXRocGcpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBEZW5fY2VsbHRvdGFsID0gbWVhbiAoRGVuX2NlbGx0b3RhbCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgU2lua1ZlbD1tZWFuKFNpbmtWZWwpLGJldGFfZD1tZWFuKGJldGFfZCksIEVfRFNfVj0gbWVhbihFX0RTX1YpLCBFX0RTX0hWPW1lYW4oRV9EU19IViksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNpbmtWZWxfbGl0aD1tZWFuIChTaW5rVmVsX2xpdGgpLCBiZXRhX2RfbGl0aD1tZWFuIChiZXRhX2RfbGl0aCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIEVsaXRoX0RTX0hWPW1lYW4gKEVsaXRoX0RTX0hWKSwgRWxpdGhfRFNfVj1tZWFuIChFbGl0aF9EU19WKSkNCg0Kc3VtbWFyeV9EUw0Kc3VtbWFyeV9EU19ieWdyb3VwDQoNCnNldHdkKCJEOi9SIHByb2dyYW0iKQ0KcmVxdWlyZShvcGVueGxzeCkNCndyaXRlLnhsc3goc3VtbWFyeV9EUywgZmlsZSA9ICJQb3N0ZG9jLVIvRXhwb3J0ZWQgVGFibGVzL3N1bW1hcnlfRFMueGxzeCIpDQp3cml0ZS54bHN4KHN1bW1hcnlfRFNfYnlncm91cCwgZmlsZSA9ICJQb3N0ZG9jLVIvRXhwb3J0ZWQgVGFibGVzL3N1bW1hcnlfRFNfYnlncm91cC54bHN4IikNCg0KYGBgDQoNCmBgYHtyfQ0KDQojOS4gcmVncmVzc2lvbiBvZiBQSUMgYW5kIHNpbmt2ZWwgb2YgY2VsbHMgYW5kIGxpdGhzDQoNCiNhLiBmb3IgY2VsbHMNClBJQ19yZWcgPC0gbG0oU2lua1ZlbH5QSUNwZXJjZWxscGcsIGRhdGE9UElDKSAjZXNzZW50aWFsbHkgcGVyZmVjdCBmaXQ6IHN1bW1hcnkgbWF5IGJlIHVucmVsaWFibGUgaGFoYQ0Kc3VtbWFyeShQSUNfcmVnKQ0KcGxvdChyZXNpZHVhbHMubG0oUElDX3JlZykpDQpsYXlvdXQobWF0cml4KDE6NCwyLDIpKQ0KcGxvdChQSUNfcmVnKQ0KDQpjb2VmKFBJQ19yZWcpDQojIGNvZWYoUElDX3JlZykNCiMoSW50ZXJjZXB0KSBQSUNwZXJjZWxscGcgDQojMC4wMTgwMDg1MiAgIDAuMDE3NzQ3NjQgDQoNCmNvcihQSUMkUElDcGVyY2VsbHBnLCBQSUMkU2lua1ZlbCkNCiNjb3IgPSAwLjk5ODkwNDINCg0KYmV0YV9yZWcgPC0gbG0oYmV0YV9kflBJQ3BlcmNlbGxwZywgZGF0YT1QSUMpDQpwbG90KHJlc2lkdWFscy5sbShiZXRhX3JlZykpDQpjb2VmKGJldGFfcmVnKQ0KI2NvZWYoYmV0YV9yZWcpDQojIChJbnRlcmNlcHQpIFBJQ3BlcmNlbGxwZyANCiMxLjYzOTIzM2UtMDcgMy4yNDMwNTRlLTA3DQoNCkVfRFNfSFZfcmVnIDwtIGxtKEVfRFNfSFZ+UElDcGVyY2VsbHBnLCBkYXRhPVBJQykNCkVfRFNfVl9yZWcgPC0gbG0oRV9EU19WflBJQ3BlcmNlbGxwZywgZGF0YT1QSUMpDQpwbG90KHJlc2lkdWFscy5sbShFX0RTX0hWX3JlZykpDQpwbG90KHJlc2lkdWFscy5sbShFX0RTX1ZfcmVnKSkNCmNvZWYoRV9EU19IVl9yZWcpDQpjb2VmKEVfRFNfVl9yZWcpDQoNCiNiLiBmb3IgbGl0aHMNCnBlcmxpdGhfcmVnIDwtIGxtIChwZXJsaXRocGd+UElDcGVyY2VsbHBnLCBkYXRhPVBJQykNCnBsb3QocmVzaWQocGVybGl0aF9yZWcpKQ0KY29lZihwZXJsaXRoX3JlZykNCnNpbmt2ZWxfbGl0aF9yZWcgPC0gbG0oU2lua1ZlbF9saXRoflBJQ3BlcmNlbGxwZywgZGF0YSA9IFBJQykNCnN1bW1hcnkoc2lua3ZlbF9saXRoX3JlZykNCnBsb3QocmVzaWR1YWxzLmxtKHNpbmt2ZWxfbGl0aF9yZWcpKQ0KbGF5b3V0KG1hdHJpeCgxOjQsMiwyKSkNCnBsb3Qoc2lua3ZlbF9saXRoX3JlZykNCmNvZWYoc2lua3ZlbF9saXRoX3JlZykNCg0KYmV0YV9saXRoX3JlZyA8LSBsbShiZXRhX2RfbGl0aH5QSUNwZXJjZWxscGcsIGRhdGE9UElDKQ0KcGxvdChyZXNpZHVhbHMubG0oYmV0YV9saXRoX3JlZykpDQpjb2VmKGJldGFfbGl0aF9yZWcpDQoNCkVsaXRoX0RTX0hWX3JlZyA8LSBsbShFbGl0aF9EU19IVn5QSUNwZXJjZWxscGcsIGRhdGE9UElDKQ0KRWxpdGhfRFNfVl9yZWcgPC0gbG0oRWxpdGhfRFNfVn5QSUNwZXJjZWxscGcsIGRhdGE9UElDKQ0KcGxvdChyZXNpZHVhbHMubG0oRWxpdGhfRFNfSFZfcmVnKSkNCnBsb3QocmVzaWR1YWxzLmxtKEVsaXRoX0RTX1ZfcmVnKSkNCmNvZWYoRWxpdGhfRFNfSFZfcmVnKQ0KY29lZihFbGl0aF9EU19WX3JlZykNCg0KYGBgDQoNCmBgYHtyfQ0KDQojIDkuIG1ha2UgbmV3IGRhdGFmcmFtZSBkZXBlbmRpbmcgb24gZXhwZXJpbWVudGFsIFBJQyB2YWx1ZXMNCiMgbWFrZSBhIHByZWRpY3Rpb24gYmFzZWQgb24gUElDIHZhbHVlcw0KcmVxdWlyZSh0cnVuY25vcm0pDQpyZXF1aXJlKFJtaXNjKQ0Kc3VtbWFyeShQSUMkUElDcGVyY2VsbHBnKQ0Kc3VtbWFyeVNFKGRhdGE9UElDLCBtZWFzdXJldmFyPSJQSUNwZXJjZWxscGciKQ0KUElDX25ld2RhdGEgPC0gYXMuZGF0YS5mcmFtZShydHJ1bmNub3JtKG49MTAwMCwgYT0tMS42LCBiPTIwLjE0LCBtZWFuPTQuNywgc2Q9Ni4xNSkpDQoNCiNyZW5hbWUgY29sdW1uLiByZW5hbWUgZnVuY3Rpb24gaW4gcGx5ciANCmxpYnJhcnkocGx5cikNClBJQ19uZXdkYXRhIDwtIHJlbmFtZSAoUElDX25ld2RhdGEsIGMgKCJydHJ1bmNub3JtKG4gPSAxMDAwLCBhID0gLTEuNiwgYiA9IDIwLjE0LCBtZWFuID0gNC43LCBzZCA9IDYuMTUpIiA9IA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUElDcGVyY2VsbHBnIikpDQoNClBJQ19uZXdkYXRhIDwtIG11dGF0ZShQSUNfbmV3ZGF0YSwgZ3JvdXAgPSBpZmVsc2UoUElDcGVyY2VsbHBnIDwgNCAsICJuYWtlZCIsICJjYWxjaWZpZWQiKSkNCg0KZ2dwbG90bHkoZ2dwbG90KGRhdGE9UElDX25ld2RhdGEsIGFlcyh4PWdyb3VwLCB5PVBJQ3BlcmNlbGxwZykpICsgZ2VvbV9ib3hwbG90KCkrZ2VvbV9wb2ludChzaXplPTIpICsNCiAgICAgICAgICAgdGhlbWVfUHVibGljYXRpb24oKSkNCg0KUElDX25ld2RhdGEkZ3JvdXAyIDwtIGNhc2Vfd2hlbigNCiAgUElDX25ld2RhdGEkUElDcGVyY2VsbHBnIDwyICB+ICJuYWtlZF9ib3V5YW50IiwNCiAgUElDX25ld2RhdGEkUElDcGVyY2VsbHBnID4yICYgUElDX25ld2RhdGEkUElDcGVyY2VsbHBnIDwgNCB+ICJuYWtlZC9jYWxjaWZpZWQgdW5jZXJ0YWluIiwNCiAgUElDX25ld2RhdGEkUElDcGVyY2VsbHBnID40ICYgUElDX25ld2RhdGEkUElDcGVyY2VsbHBnIDwgMTAgfiAibW9kZXJhdGVseSBjYWxjaWZpZWQiLA0KICBQSUNfbmV3ZGF0YSRQSUNwZXJjZWxscGcgPjEwIH4gInN0cm9uZ2x5IGNhbGNpZmllZCIsIA0KICBUUlVFIH4gYXMuY2hhcmFjdGVyKFBJQ19uZXdkYXRhJFBJQ3BlcmNlbGxwZykNCikNCg0KUElDX25ld2RhdGEkZ3JvdXAyIDwtIGZhY3RvciAoUElDX25ld2RhdGEkZ3JvdXAyLGxldmVscz0gYygibmFrZWRfYm91eWFudCIsICJuYWtlZC9jYWxjaWZpZWQgdW5jZXJ0YWluIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAibW9kZXJhdGVseSBjYWxjaWZpZWQiLCAic3Ryb25nbHkgY2FsY2lmaWVkIiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygibmFrZWQiLCAibmFrZWQvY2FsY2lmaWVkIHVuY2VydGFpbiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAibW9kZXJhdGVseSBjYWxjaWZpZWQiLCAic3Ryb25nbHkgY2FsY2lmaWVkIikpDQoNCmdncGxvdGx5KGdncGxvdChkYXRhPVBJQ19uZXdkYXRhLCBhZXMoeD1ncm91cDIsIHk9UElDcGVyY2VsbHBnKSkgKyBnZW9tX2JveHBsb3QoKStnZW9tX3BvaW50KHNpemU9MikNCiAgICAgICAgICt0aGVtZV9QdWJsaWNhdGlvbigpKQ0KDQojYS4gZm9yIGhvc3QNClBJQ19uZXdkYXRhJFNpbmtWZWwucHJlZCA8LSBwcmVkaWN0KFBJQ19yZWcsIGRhdGEuZnJhbWUoUElDX25ld2RhdGEpKQ0KUElDX25ld2RhdGFfcmVnIDwtIGxtKFNpbmtWZWwucHJlZH5QSUNwZXJjZWxscGcsIGRhdGE9UElDX25ld2RhdGEpIA0KY29lZihQSUNfbmV3ZGF0YV9yZWcpDQojc2FtZSBjb2VmIGFzIFBJQ19yZWcNCiM+IGNvZWYoUElDX25ld2RhdGFfcmVnKQ0KIyhJbnRlcmNlcHQpIFBJQ3BlcmNlbGxwZyANCiMwLjAxODAwODUyICAgMC4wMTc3NDc2NCANCg0KcGxvdChyZXNpZChQSUNfbmV3ZGF0YV9yZWcpKQ0KDQpnZ3Bsb3QoZGF0YT1QSUNfbmV3ZGF0YSwgYWVzKHg9UElDcGVyY2VsbHBnLCB5PVNpbmtWZWwucHJlZCkpICtnZW9tX3BvaW50KHNpemU9MikgK3RoZW1lX1B1YmxpY2F0aW9uKCkrDQogIGxhYnMoeSA9IGV4cHJlc3Npb24oIlByZWRpY3RlZCBTaW5raW5nIHZlbG9jaXR5In4oIm0ifmRheV4tMSkpLCB4ID0gZXhwcmVzc2lvbigiUElDIn5jZWxsXi0xKSkgDQoNClBJQ19uZXdkYXRhJGJldGEucHJlZCA8LSBwcmVkaWN0KGJldGFfcmVnLCBkYXRhLmZyYW1lKFBJQ19uZXdkYXRhKSkNClBJQ19uZXdkYXRhJEVfRFNfVi5wcmVkIDwtIHByZWRpY3QoRV9EU19WX3JlZywgZGF0YS5mcmFtZShQSUNfbmV3ZGF0YSkpDQpQSUNfbmV3ZGF0YSRFX0RTX0hWLnByZWQgPC0gcHJlZGljdChFX0RTX0hWX3JlZywgZGF0YS5mcmFtZShQSUNfbmV3ZGF0YSkpDQoNCmdncGxvdChkYXRhPVBJQ19uZXdkYXRhLCBhZXMoeD1QSUNwZXJjZWxscGcsIHk9RV9EU19WLnByZWQpKSArZ2VvbV9wb2ludChzaXplPTUsIGFlcyhjb2xvcj1ncm91cDIpKSArDQogICAgdGhlbWVfUHVibGljYXRpb24oKSArIGdlb21fc21vb3RoKCkgKw0KICAgIHNjYWxlX3lfbG9nMTAoDQogICAgICAgIGJyZWFrcyA9IHNjYWxlczo6dHJhbnNfYnJlYWtzKCJsb2cxMCIsIGZ1bmN0aW9uKHgpIDEwXngsIG49NCksDQogICAgICAgIGxhYmVscyA9IHNjYWxlczo6dHJhbnNfZm9ybWF0KCJsb2cxMCIsIHNjYWxlczo6bWF0aF9mb3JtYXQoMTBeLngpKSkgKyBhbm5vdGF0aW9uX2xvZ3RpY2tzKHNpZGVzPSJsIikgKw0KICAgIGxhYnMoeSA9IGV4cHJlc3Npb24oInZpcmFsIGVuY291bnRlcnMgIiB+IGRheV4tMX5jZWxsXi0xKSwgeCA9IGV4cHJlc3Npb24oIlBJQyJ+Y2VsbF4tMSkpICsNCiAgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpKQ0KDQpnZ3Bsb3QoZGF0YT1QSUNfbmV3ZGF0YSwgYWVzKHg9UElDcGVyY2VsbHBnLCB5PUVfRFNfSFYucHJlZCkpICtnZW9tX3BvaW50KHNpemU9NSwgYWVzKGNvbG9yPWdyb3VwMikpICsNCiAgICB0aGVtZV9QdWJsaWNhdGlvbigpICsgZ2VvbV9zbW9vdGgoKSArDQogICAgc2NhbGVfeV9sb2cxMCgNCiAgICAgICAgYnJlYWtzID0gc2NhbGVzOjp0cmFuc19icmVha3MoImxvZzEwIiwgZnVuY3Rpb24oeCkgMTBeeCwgbj00KSwNCiAgICAgICAgbGFiZWxzID0gc2NhbGVzOjp0cmFuc19mb3JtYXQoImxvZzEwIiwgc2NhbGVzOjptYXRoX2Zvcm1hdCgxMF4ueCkpKSArIGFubm90YXRpb25fbG9ndGlja3Moc2lkZXM9ImwiKSArDQogICAgbGFicyh5ID0gZXhwcmVzc2lvbigidmlyYWwgZW5jb3VudGVycyAiIH4gY21eLTN+ZGF5Xi0xKSwgeCA9IGV4cHJlc3Npb24oIlBJQyJ+Y2VsbF4tMSkpICsNCiAgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpKQ0KDQpQSUNiZXRhX25ldyA8LSBnZ3Bsb3QoZGF0YT1QSUNfbmV3ZGF0YSwgYWVzKHg9UElDcGVyY2VsbHBnLCB5PWJldGEucHJlZCkpICsNCiAgZ2VvbV9wb2ludChzaXplPTUsIGFlcyhjb2xvcj1QSUNwZXJjZWxscGcpKSsNCiAgc2NhbGVfY29sb3VyX2dyYWRpZW50KG5hbWU9IlBJQyIsIGd1aWRlPWd1aWRlX2NvbG9yYmFyKGRpcmVjdGlvbiA9ICJ2ZXJ0aWNhbCIsIGJhcmhlaWdodD0xMCkpKw0KICB0aGVtZV9QdWJsaWNhdGlvbigpICsgDQogIHNjYWxlX3lfbG9nMTAoDQogICAgICAgIGJyZWFrcyA9IHNjYWxlczo6dHJhbnNfYnJlYWtzKCJsb2cxMCIsIGZ1bmN0aW9uKHgpIDEwXngsIG49NCksDQogICAgICAgIGxhYmVscyA9IHNjYWxlczo6dHJhbnNfZm9ybWF0KCJsb2cxMCIsIHNjYWxlczo6bWF0aF9mb3JtYXQoMTBeLngpKSkgKyBhbm5vdGF0aW9uX2xvZ3RpY2tzKHNpZGVzPSJsIikgKw0KICBsYWJzKHkgPSBleHByZXNzaW9uKGJldGF+KCJQcmVkaWN0ZWQgRW5jb3VudGVycyJ+Y21eM35kYXleLTEpKSwgeCA9IGV4cHJlc3Npb24oIlBJQyJ+Y2VsbF4tMSkpKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiKQ0KUElDYmV0YV9uZXcNCg0KI2IuIGZvciBsaXRocw0KUElDX25ld2RhdGEkcGVybGl0aHBnLnByZWQgPC0gcHJlZGljdChwZXJsaXRoX3JlZywgZGF0YS5mcmFtZShQSUNfbmV3ZGF0YSkpDQpQSUNfbmV3ZGF0YSRTaW5rVmVsLnByZWQubGl0aCA8LSBwcmVkaWN0KHNpbmt2ZWxfbGl0aF9yZWcsIGRhdGEuZnJhbWUoUElDX25ld2RhdGEpKQ0Kc2lua3ZlbF9saXRoX3JlZy5wcmVkIDwtIGxtKFNpbmtWZWwucHJlZC5saXRoflBJQ3BlcmNlbGxwZywgZGF0YT1QSUNfbmV3ZGF0YSkgDQpjb2VmKHNpbmt2ZWxfbGl0aF9yZWcucHJlZCkNCiNzYW1lIGNvZWYgYXMgc2lua3ZlbF9saXRoX3JlZw0KIz4gY29lZihzaW5rdmVsX2xpdGhfcmVnLnByZWQpDQojKEludGVyY2VwdCkgUElDcGVyY2VsbHBnIA0KIyAwLjAxNjcyNzUzICAgMC4wMTExNTE2OSANCg0KcGxvdChyZXNpZChzaW5rdmVsX2xpdGhfcmVnLnByZWQpKQ0KDQpnZ3Bsb3QoZGF0YT1QSUNfbmV3ZGF0YSwgYWVzKHg9cGVybGl0aHBnLnByZWQsIHk9U2lua1ZlbC5wcmVkLmxpdGgpKSArZ2VvbV9wb2ludChzaXplPTIpICt0aGVtZV9QdWJsaWNhdGlvbigpKw0KICBsYWJzKHkgPSBleHByZXNzaW9uKCJQcmVkaWN0ZWQgU2lua2luZyB2ZWxvY2l0eSBvZiBMaXRocyJ+KCJtIn5kYXleLTEpKSwgeCA9IGV4cHJlc3Npb24oIlBJQyJ+bGl0aF4tMSkpIA0KDQpQSUNfbmV3ZGF0YSRiZXRhLnByZWQubGl0aCA8LSBwcmVkaWN0KGJldGFfbGl0aF9yZWcsIGRhdGEuZnJhbWUoUElDX25ld2RhdGEpKQ0KUElDX25ld2RhdGEkRV9EU19WLnByZWQubGl0aCA8LSBwcmVkaWN0KEVsaXRoX0RTX0hWX3JlZywgZGF0YS5mcmFtZShQSUNfbmV3ZGF0YSkpDQpQSUNfbmV3ZGF0YSRFX0RTX0hWLnByZWQubGl0aCA8LSBwcmVkaWN0KEVsaXRoX0RTX0hWX3JlZywgZGF0YS5mcmFtZShQSUNfbmV3ZGF0YSkpDQoNCmdncGxvdChkYXRhPVBJQ19uZXdkYXRhLCBhZXMoeD1QSUNwZXJjZWxscGcsIHk9RV9EU19WLnByZWQubGl0aCkpICtnZW9tX3BvaW50KHNpemU9NSwgYWVzKGNvbG9yPWdyb3VwMikpICsNCiAgICB0aGVtZV9QdWJsaWNhdGlvbigpICsgZ2VvbV9zbW9vdGgoKSArDQogICAgc2NhbGVfeV9sb2cxMCgNCiAgICAgICAgYnJlYWtzID0gc2NhbGVzOjp0cmFuc19icmVha3MoImxvZzEwIiwgZnVuY3Rpb24oeCkgMTBeeCwgbj00KSwNCiAgICAgICAgbGFiZWxzID0gc2NhbGVzOjp0cmFuc19mb3JtYXQoImxvZzEwIiwgc2NhbGVzOjptYXRoX2Zvcm1hdCgxMF4ueCkpKSArIGFubm90YXRpb25fbG9ndGlja3Moc2lkZXM9ImwiKSArDQogICAgbGFicyh5ID0gZXhwcmVzc2lvbigidmlyYWwgZW5jb3VudGVycyAiIH4gZGF5Xi0xfmNlbGxeLTEpLCB4ID0gZXhwcmVzc2lvbigiUElDIn5saXRoXi0xKSkgKw0KICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpDQoNCmdncGxvdChkYXRhPVBJQ19uZXdkYXRhLCBhZXMoeD1QSUNwZXJjZWxscGcsIHk9RV9EU19IVi5wcmVkLmxpdGgpKSArZ2VvbV9wb2ludChzaXplPTUsIGFlcyhjb2xvcj1ncm91cDIpKSArDQogICAgdGhlbWVfUHVibGljYXRpb24oKSArIGdlb21fc21vb3RoKCkgKw0KICAgIHNjYWxlX3lfbG9nMTAoDQogICAgICAgIGJyZWFrcyA9IHNjYWxlczo6dHJhbnNfYnJlYWtzKCJsb2cxMCIsIGZ1bmN0aW9uKHgpIDEwXngsIG49NCksDQogICAgICAgIGxhYmVscyA9IHNjYWxlczo6dHJhbnNfZm9ybWF0KCJsb2cxMCIsIHNjYWxlczo6bWF0aF9mb3JtYXQoMTBeLngpKSkgKyBhbm5vdGF0aW9uX2xvZ3RpY2tzKHNpZGVzPSJsIikgKw0KICAgIGxhYnMoeSA9IGV4cHJlc3Npb24oInZpcmFsIGVuY291bnRlcnMgIiB+IGNtXi0zfmRheV4tMSksIHggPSBleHByZXNzaW9uKCJQSUMifmxpdGheLTEpKSArDQogIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSkNCg0KUElDYmV0YV9uZXcubGl0aCA8LSBnZ3Bsb3QoZGF0YT1QSUNfbmV3ZGF0YSwgYWVzKHg9cGVybGl0aHBnLnByZWQsIHk9YmV0YS5wcmVkLmxpdGgpKSArDQogIGdlb21fcG9pbnQoc2l6ZT01LCBhZXMoY29sb3I9UElDcGVyY2VsbHBnKSkrDQogIHNjYWxlX2NvbG91cl9ncmFkaWVudChuYW1lPSJQSUMiLCBndWlkZT1ndWlkZV9jb2xvcmJhcihkaXJlY3Rpb24gPSAidmVydGljYWwiLCBiYXJoZWlnaHQ9MTApKSsNCiAgdGhlbWVfUHVibGljYXRpb24oKSArIA0KICBzY2FsZV95X2xvZzEwKA0KICAgICAgICBicmVha3MgPSBzY2FsZXM6OnRyYW5zX2JyZWFrcygibG9nMTAiLCBmdW5jdGlvbih4KSAxMF54LCBuPTQpLA0KICAgICAgICBsYWJlbHMgPSBzY2FsZXM6OnRyYW5zX2Zvcm1hdCgibG9nMTAiLCBzY2FsZXM6Om1hdGhfZm9ybWF0KDEwXi54KSkpICsgYW5ub3RhdGlvbl9sb2d0aWNrcyhzaWRlcz0ibCIpICsNCiAgbGFicyh5ID0gZXhwcmVzc2lvbihiZXRhfigiUHJlZGljdGVkIEVuY291bnRlcnMgb2YgbGl0aCAiIH5jbV4zfmRheV4tMSkpLCB4ID0gZXhwcmVzc2lvbigiUElDIn5saXRoXi0xKSkrDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpDQpQSUNiZXRhX25ldy5saXRoDQoNCiNzdW1tYXJpZXMNCnN1bW1hcnlfRFNfbmV3ZGF0YV9ieWdyb3VwMiA8LSBkZHBseShQSUNfbmV3ZGF0YSwgLihncm91cDIpLCBzdW1tYXJpemUsICBQSUNwZXJjZWxscGc9bWVhbihQSUNwZXJjZWxscGcpLCBTaW5rVmVsLnByZWQ9bWVhbihTaW5rVmVsLnByZWQpLGJldGEucHJlZD0gbWVhbiAoYmV0YS5wcmVkKSwgRV9EU19WLnByZWQ9IG1lYW4oRV9EU19WLnByZWQpLCBFX0RTX0hWLnByZWQ9bWVhbihFX0RTX0hWLnByZWQpKQ0KDQpzdW1tYXJ5X0RTX2J5Z3JvdXAucHJlZCA8LSBkZHBseShQSUNfbmV3ZGF0YSwgLihncm91cDIpLCBzdW1tYXJpemUsICBQSUNwZXJjZWxscGc9bWVhbihQSUNwZXJjZWxscGcpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwZXJsaXRocGcucHJlZCA9IG1lYW4ocGVybGl0aHBnLnByZWQpLCBTaW5rVmVsLnByZWQ9bWVhbihTaW5rVmVsLnByZWQpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJldGEucHJlZD0gbWVhbiAoYmV0YS5wcmVkKSwgRV9EU19WLnByZWQ9IG1lYW4oRV9EU19WLnByZWQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBFX0RTX0hWLnByZWQ9bWVhbihFX0RTX0hWLnByZWQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBTaW5rVmVsLnByZWQubGl0aD1tZWFuKFNpbmtWZWwucHJlZC5saXRoKSxiZXRhLnByZWQubGl0aD0gbWVhbiAoYmV0YS5wcmVkLmxpdGgpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIEVfRFNfVi5wcmVkLmxpdGg9IG1lYW4oRV9EU19WLnByZWQubGl0aCksIEVfRFNfSFYucHJlZC5saXRoPW1lYW4oRV9EU19IVi5wcmVkLmxpdGgpKQ0KDQpzdW1tYXJ5X0RTX2J5Z3JvdXAucHJlZA0KDQp3cml0ZS54bHN4KHN1bW1hcnlfRFNfYnlncm91cC5wcmVkLCBmaWxlID0gIlBvc3Rkb2MtUi9FeHBvcnRlZCBUYWJsZXMvc3VtbWFyeV9EU19ieWdyb3VwLnByZWQueGxzeCIpDQoNCg0KYGBgDQoNCnR1cmJ1bGVuY2UNCg0KYGBge3J9DQojVFVSQlVMRU5DRQ0KI2Rpc3JhdGUgaXMgY20yL3MzDQoNCiNtYWtlIGRhdGEgZnJhbWUNCg0KZGlzcmF0ZSA8LSByZXBfbGVuIChjICgxICVvJSAxMF4oc2VxKC04LC0yLCAwLjUpKSksIGxlbmd0aC5vdXQ9MjYpDQpjYWxjIDwtIHJlcF9sZW4oYygiY2FsY2lmaWVkIiksIGxlbmd0aC5vdXQ9MTMpDQpuYWtlZCA8LSByZXBfbGVuKGMoIm5ha2VkIiksIGxlbmd0aC5vdXQ9MTMpDQpsaXRoIDwtIHJlcF9sZW4oYygibGl0aCIpLCBsZW5ndGgub3V0PTEzKQ0KZ3JvdXAgPC0gYyhjYWxjLCBuYWtlZCwgbGl0aCkNCnR1cmIgPC0gYXMuZGF0YS5mcmFtZShjYmluZChkaXNyYXRlLCBncm91cCkpDQoNCnR1cmIkcmFkIDwtIGNhc2Vfd2hlbigNCiAgICB0dXJiJGdyb3VwID09Im5ha2VkIiB+IDEuOEUtNiwNCiAgICB0dXJiJGdyb3VwID09ImNhbGNpZmllZCIgfiAyLjNFLTYsDQogICAgdHVyYiRncm91cCA9PSJsaXRoIiB+IDJFLTYsDQogICAgVFJVRSB+IGFzLm51bWVyaWModHVyYiRncm91cCkNCikNCiN0dXJiIDwtIG11dGF0ZSh0dXJiLCByYWQgPSBpZmVsc2UoZ3JvdXAgPT0gIm5ha2VkIiAsICAxLjhFLTYsICAyLjNFLTYpKSAjaW4gbQ0KDQp0dXJiJGRpc3JhdGUgPC0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIodHVyYiRkaXNyYXRlKSkNCg0KdHVyYiRLb2wgPC0gKCh2XjMvdHVyYiRkaXNyYXRlKV4wLjI1KSoxMDAgI0tvbG1vZ29yb3YgbGVuZ3RoIHNjYWxlIGluIGNtDQojZXZlcnl0aGluZyBpcyBiZWxvdyAxIGNtLCB1c2UgZXFuIDIgaW4gVEsgDQoNCnR1cmIkYmV0YV9kIDwtICg0LjIqcGkqKCh0dXJiJGRpc3JhdGUvKHYqMTAwXjIpKV4wLjUpKigoKHR1cmIkcmFkK1JlaHYpKjEwMCleMykpKjg2NDAwIA0KDQp0dXJiJGJldGFfSGVpZGkgPC0gKDAuNDIqcGkqKCh0dXJiJGRpc3JhdGUvKHYqMTAwXjIpKV4wLjUpKigoKHR1cmIkcmFkK1JlaHYpKjEwMCleMykpKjg2NDAwDQoNCiNjaGVjayBlbmNvdW50ZXJzDQoNCiN1c2UgVEssIGluIGNtMyBzDQp0dXJiJEVfdHVyYl9IViA8LSAodHVyYiRiZXRhX2QqaG9zdG51bSp2aXJudW0pICNFIGNhbGN1bGF0ZWQgd2l0aCBWaXJ1cyBhbmQgSG9zdCAoMTA6MSBNT0kpDQp0dXJiJEVfdHVyYl9WIDwtICh0dXJiJGJldGFfZCp2aXJudW0pICNFIGNhbGN1bGF0ZWQgd2l0aCB2aXJ1cyBvbmx5DQoNCiNicmVha3MgPC0gMTBeKC0xMDoxMCkNCiNtaW5vcl9icmVha3MgPC0gcmVwKDE6OSwgMjEpKigxMF5yZXAoLTEwOjEwLCBlYWNoPTkpKQ0KDQpnZ3Bsb3QoZGF0YSA9IHR1cmIsIGFlcyh4ID0gZGlzcmF0ZSwgeSA9IGJldGFfZCwgY29sb3I9Z3JvdXApKSArIGdlb21fcG9pbnQoc2l6ZSA9NSkgKw0KICBzY2FsZV95X2xvZzEwKA0KICAgICAgICBicmVha3MgPSBzY2FsZXM6OnRyYW5zX2JyZWFrcygibG9nMTAiLCBmdW5jdGlvbih4KSAxMF54LCBuPTQpLA0KICAgICAgICBsYWJlbHMgPSBzY2FsZXM6OnRyYW5zX2Zvcm1hdCgibG9nMTAiLCBzY2FsZXM6Om1hdGhfZm9ybWF0KDEwXi54KSkpICsNCiAgc2NhbGVfeF9sb2cxMCgNCiAgICAgICAgYnJlYWtzID0gc2NhbGVzOjp0cmFuc19icmVha3MoImxvZzEwIiwgZnVuY3Rpb24oeCkgMTBeeCwgbj00KSwNCiAgICAgICAgbGFiZWxzID0gc2NhbGVzOjp0cmFuc19mb3JtYXQoImxvZzEwIiwgc2NhbGVzOjptYXRoX2Zvcm1hdCgxMF4ueCkpKSArDQogIGFubm90YXRpb25fbG9ndGlja3MoKSArDQogIHRoZW1lX1B1YmxpY2F0aW9uKCkgKw0KICBsYWJzKHkgPSBleHByZXNzaW9uKGJldGF+KCJwcmVkaWN0ZWQgZW5jb3VudGVycyAiIH5jbV4zfmRheV4tMSkpLCANCiAgICAgICB4ID0gZXhwcmVzc2lvbigiZGlzc2lwYXRpb24gcmF0ZSAifihtXjJ+c14tMykpKSArDQogICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpDQogIA0KDQpsaWJyYXJ5KHNjYWxlcykNCg0KZ2dwbG90KGRhdGEgPSB0dXJiLCBhZXMoeCA9IGRpc3JhdGUsIHkgPSBFX3R1cmJfViwgY29sb3I9Z3JvdXApKSArIGdlb21fcG9pbnQoc2l6ZSA9NSkgKw0KICAgc2NhbGVfeV9sb2cxMCgNCiAgICAgICAgYnJlYWtzID0gc2NhbGVzOjp0cmFuc19icmVha3MoImxvZzEwIiwgZnVuY3Rpb24oeCkgMTBeeCwgbj00KSwNCiAgICAgICAgbGFiZWxzID0gc2NhbGVzOjp0cmFuc19mb3JtYXQoImxvZzEwIiwgc2NhbGVzOjptYXRoX2Zvcm1hdCgxMF4ueCkpKSArDQogIHNjYWxlX3hfbG9nMTAoDQogICAgICAgIGJyZWFrcyA9IHNjYWxlczo6dHJhbnNfYnJlYWtzKCJsb2cxMCIsIGZ1bmN0aW9uKHgpIDEwXngsIG49OCksDQogICAgICAgIGxhYmVscyA9IHNjYWxlczo6dHJhbnNfZm9ybWF0KCJsb2cxMCIsIHNjYWxlczo6bWF0aF9mb3JtYXQoMTBeLngpKSkgKw0KICBhbm5vdGF0aW9uX2xvZ3RpY2tzKCkrDQogIHRoZW1lX1B1YmxpY2F0aW9uKCkrDQogIGxhYnMoeSA9IGV4cHJlc3Npb24oInZpcmFsIGVuY291bnRlcnMgIiB+IGRheV4tMX5jZWxsXi0xKSwgeCA9IGV4cHJlc3Npb24oImRpc3NpcGF0aW9uIHJhdGUgIn4obV4yfnNeLTMpKSkgKw0KICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpDQoNCmdncGxvdChkYXRhID0gdHVyYiwgYWVzKHggPSBkaXNyYXRlLCB5ID0gRV90dXJiX0hWLCBjb2xvcj1ncm91cCkpICsgZ2VvbV9wb2ludChzaXplID01KSArDQogICBzY2FsZV95X2xvZzEwKA0KICAgICAgICBicmVha3MgPSBzY2FsZXM6OnRyYW5zX2JyZWFrcygibG9nMTAiLCBmdW5jdGlvbih4KSAxMF54LCBuPTQpLA0KICAgICAgICBsYWJlbHMgPSBzY2FsZXM6OnRyYW5zX2Zvcm1hdCgibG9nMTAiLCBzY2FsZXM6Om1hdGhfZm9ybWF0KDEwXi54KSkpICsNCiAgc2NhbGVfeF9sb2cxMCgNCiAgICAgICAgYnJlYWtzID0gc2NhbGVzOjp0cmFuc19icmVha3MoImxvZzEwIiwgZnVuY3Rpb24oeCkgMTBeeCwgbj03KSwNCiAgICAgICAgbGFiZWxzID0gc2NhbGVzOjp0cmFuc19mb3JtYXQoImxvZzEwIiwgc2NhbGVzOjptYXRoX2Zvcm1hdCgxMF4ueCkpKSArDQogIGFubm90YXRpb25fbG9ndGlja3MoKSsNCiAgdGhlbWVfUHVibGljYXRpb24oKSsNCiAgbGFicyh5ID0gZXhwcmVzc2lvbigidmlyYWwgZW5jb3VudGVycyAiIH4gY21eLTN+ZGF5Xi0xKSx4ID0gZXhwcmVzc2lvbigiZGlzc2lwYXRpb24gcmF0ZSAifihtXjJ+c14tMykpKSArDQogIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSkNCg0KYGBgDQoNCmFkZCBiZXRhIGtlcm5lbHMgYW5kIHBsb3QNCg0KYGBge3J9DQojZXh0cmFjdCBtZWFuIGJldGFzIGZyb20gUElDX25ld2RhdGENCmJldGFfRFMgPC0gc3VtbWFyeVNFIChQSUNfbmV3ZGF0YSwgbWVhc3VyZXZhciA9ICJiZXRhLnByZWQiLCBncm91cHZhcnMgPSBjKCJncm91cCIsICJncm91cDIiKSkNCmxpdGhfRFMgPC1zdW1tYXJ5U0UgKFBJQ19uZXdkYXRhLCBtZWFzdXJldmFyID0gImJldGEucHJlZC5saXRoIiwgZ3JvdXB2YXJzID0gYygiZ3JvdXAiLCAiZ3JvdXAyIikpDQoNCmxpdGhfRFMkZ3JvdXAxIDwtIGxpdGhfRFMkZ3JvdXANCmxpdGhfRFMkZ3JvdXAgPC0gImxpdGgiDQoNCiNzZXBhcmF0ZSBkYXRhIGZyYW1lcyBmb3IgaG9zdCBhbmQgbGl0aHMNCg0KYWxsIDwtIFJlZHVjZShmdW5jdGlvbih4LHkpIG1lcmdlKHgseSxieT0iZ3JvdXAiLGFsbD1UUlVFKSAsDQogICAgICAgICAgICAgIGxpc3QoQk0sIGJldGFfRFMsIHR1cmIgJT4lIGZpbHRlcihncm91cCAlaW4lIGMoIm5ha2VkIiwgImNhbGNpZmllZCIpKSkpDQoNCg0KYWxsLmxpdGhzICA8LSBSZWR1Y2UoZnVuY3Rpb24oeCx5KSBtZXJnZSh4LHksYnk9Imdyb3VwIixhbGw9VFJVRSkgLA0KICAgICAgICAgICAgICAgICAgICAgbGlzdChsaXRoX0RTLCB0dXJiICU+JSBmaWx0ZXIoZ3JvdXAgJWluJSBjKCJsaXRoIikpKSkNCg0KI2JldGFfZC54PUJNLCBiZXRhLnByZWQ9RFMsIGJldGFwcmVkLmxpdGg9IGJldGEucHJlZC5saXRoLCBiZXRhX2QueT10dXJiDQoNCiNyZW5hbWUgYmV0YS5wcmVkIHRvIGJldGFfcHJlZCBzbyBJIGNhbiB1c2UgZ3JlcC4gDQojYWxsIDwtIHJlbmFtZSAoYWxsLCBjKCJiZXRhX2QueCIgPSAiYmV0YV9CTSIsICJiZXRhLnByZWQiID0gImJldGFfRFMiLCAiYmV0YV9kLnkiID0gImJldGFfdHVyYiIpKQ0KDQpsaWJyYXJ5KGRhdGEudGFibGUpDQpOVCA9IGRhdGEudGFibGUoYWxsLCBrZXk9Imdyb3VwMiIpDQphbGxiZXRhcyA9IE5UWywgbGlzdChncm91cD1ncm91cCwgZGlzcmF0ZT1kaXNyYXRlLCBiZXRhX0JNPWJldGFfZC54LCBiZXRhX0RTPWJldGEucHJlZCwgYmV0YV90dXJiID0gYmV0YV9kLnksIA0KICAgICAgICAgICAgICAgICAgICAgYmV0YV9CTV9EUyA9YmV0YV9kLnggKyBiZXRhLnByZWQsDQogICAgICAgICAgICAgICAgICAgICBiZXRhX0RTX3R1cmIgPSBiZXRhLnByZWQgKyBiZXRhX2QueSwNCiAgICAgICAgICAgICAgICAgICAgIGJldGFfQk1fdHVyYiA9IGJldGFfZC54ICsgYmV0YV9kLnksDQogICAgICAgICAgICAgICAgICAgICBiZXRhX2FsbCA9IGJldGFfZC54ICsgYmV0YV9kLnkgKyBiZXRhLnByZWQpLCANCiAgICAgICAgICAgICAgYnk9YygiZ3JvdXAyIildDQoNCk5UMiA8LSBkYXRhLnRhYmxlKGFsbC5saXRocywga2V5ID0gImdyb3VwMiIpDQphbGxiZXRhcy5saXRoID0gTlQyWywgbGlzdChncm91cD1ncm91cCwgZ3JvdXAxPWdyb3VwMSwgZGlzcmF0ZT1kaXNyYXRlLCBiZXRhX0RTLmxpdGg9YmV0YS5wcmVkLmxpdGgsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBiZXRhX3R1cmIubGl0aCA9IGJldGFfZCwgDQogICAgICAgICAgICAgICAgICAgICBiZXRhX0RTX3R1cmIubGl0aCA9YmV0YS5wcmVkLmxpdGggKyBiZXRhX2QpLCANCiAgICAgICAgICAgICAgICAgICAgIGJ5PWMoImdyb3VwMiIpXQ0KDQpnZ3Bsb3QoYWxsYmV0YXMsIGFlcyhkaXNyYXRlLCB5ID0gdmFsdWUsIGNvbG9yPWdyb3VwMikpICsgDQogICAgZ2VvbV9saW5lKGFlcyh5ID0gYmV0YV9EU190dXJiLCBsaW5ldHlwZSA9ICJEUyt0dXJiIiksIHNpemU9MSkgKyANCiAgICBnZW9tX2xpbmUoYWVzKHkgPSBiZXRhX2FsbCwgbGluZXR5cGUgPSAiQk0rRFMrdHVyYiIpLCBzaXplPTEpKw0KICAgIGdlb21fbGluZShhZXMoeSA9IGJldGFfdHVyYiwgbGluZXR5cGUgPSAidHVyYiIpLCBzaXplPTEpKw0KICAgIGdlb21fbGluZShkYXRhID0gYWxsYmV0YXMubGl0aCwgYWVzKHk9IGJldGFfRFNfdHVyYi5saXRoLCBsaW5ldHlwZT0iRFMrdHVyYi5saXRoIikpICsNCiAgICBzY2FsZV95X2xvZzEwKA0KICAgICAgICBicmVha3MgPSBzY2FsZXM6OnRyYW5zX2JyZWFrcygibG9nMTAiLCBmdW5jdGlvbih4KSAxMF54LCBuPTQpLA0KICAgICAgICBsYWJlbHMgPSBzY2FsZXM6OnRyYW5zX2Zvcm1hdCgibG9nMTAiLCBzY2FsZXM6Om1hdGhfZm9ybWF0KDEwXi54KSkpICsNCiAgICBzY2FsZV94X2xvZzEwKA0KICAgICAgICBicmVha3MgPSBzY2FsZXM6OnRyYW5zX2JyZWFrcygibG9nMTAiLCBmdW5jdGlvbih4KSAxMF54LCBuPTcpLA0KICAgICAgICBsYWJlbHMgPSBzY2FsZXM6OnRyYW5zX2Zvcm1hdCgibG9nMTAiLCBzY2FsZXM6Om1hdGhfZm9ybWF0KDEwXi54KSkpICsNCiAgICBhbm5vdGF0aW9uX2xvZ3RpY2tzKCkrDQogICAgdGhlbWVfUHVibGljYXRpb24oKSArDQogICAgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLCBsZWdlbmQua2V5LndpZHRoPXVuaXQoMiwiY20iKSkrDQogICAgZ3VpZGVzKGxpbmV0eXBlPWd1aWRlX2xlZ2VuZChucm93ICA9NCksIGNvbG91cj1ndWlkZV9sZWdlbmQobnJvdz00LGJ5cm93PVRSVUUpKSANCg0KZ2dwbG90KGFsbGJldGFzLCBhZXMoZGlzcmF0ZSwgeSA9IHZhbHVlLCBjb2xvcj1ncm91cDIpKSArIA0KICBnZW9tX2xpbmUoYWVzKHkgPSBiZXRhX0RTX3R1cmIsIGxpbmV0eXBlID0gIkRTK3R1cmIiKSwgc2l6ZT0xKSArIA0KICBnZW9tX2xpbmUoZGF0YSA9IGFsbGJldGFzLmxpdGgsIGFlcyh5PSBiZXRhX0RTX3R1cmIubGl0aCwgbGluZXR5cGU9IkRTK3R1cmIubGl0aCIpKSArIA0KICBzY2FsZV95X2xvZzEwKA0KICAgICAgICBicmVha3MgPSBzY2FsZXM6OnRyYW5zX2JyZWFrcygibG9nMTAiLCBmdW5jdGlvbih4KSAxMF54LCBuPTQpLA0KICAgICAgICBsYWJlbHMgPSBzY2FsZXM6OnRyYW5zX2Zvcm1hdCgibG9nMTAiLCBzY2FsZXM6Om1hdGhfZm9ybWF0KDEwXi54KSkpICsNCiAgc2NhbGVfeF9sb2cxMCgNCiAgICAgICAgYnJlYWtzID0gc2NhbGVzOjp0cmFuc19icmVha3MoImxvZzEwIiwgZnVuY3Rpb24oeCkgMTBeeCwgbj03KSwNCiAgICAgICAgbGFiZWxzID0gc2NhbGVzOjp0cmFuc19mb3JtYXQoImxvZzEwIiwgc2NhbGVzOjptYXRoX2Zvcm1hdCgxMF4ueCkpKSArDQogIGFubm90YXRpb25fbG9ndGlja3MoKSsNCiAgdGhlbWVfUHVibGljYXRpb24oKSArDQogIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwgbGVnZW5kLmtleS53aWR0aD11bml0KDIsImNtIikpKw0KICBndWlkZXMobGluZXR5cGU9Z3VpZGVfbGVnZW5kKG5yb3cgID00KSwgY29sb3VyPWd1aWRlX2xlZ2VuZChucm93PTQsYnlyb3c9VFJVRSkpIA0KDQojZW5jb3VudGVycw0KDQojbWVsdCBkYXRhDQoNCmFsbGJldGFzLm1lbHQgPC0gbWVsdCAoYWxsYmV0YXMsIGlkLnZhcnMgPSBjKCJncm91cDIiLCAiZ3JvdXAiLCAiZGlzcmF0ZSIpLCB2YWx1ZS5uYW1lID0gImJldGFfZCIsIA0KICAgICAgICAgICAgICAgICAgICAgICB2YXJpYWJsZS5uYW1lID0gImJldGFrZXJuZWwiKQ0KDQphbGxiZXRhcy5tZWx0JEVfViA8LSBhbGxiZXRhcy5tZWx0JGJldGFfZCp2aXJudW0NCmFsbGJldGFzLm1lbHQkRV9IViA8LSBhbGxiZXRhcy5tZWx0JGJldGFfZCp2aXJudW0qaG9zdG51bQ0KDQphbGxiZXRhcy5tZWx0LmxpdGggPC0gbWVsdCAoYWxsYmV0YXMubGl0aCwgaWQudmFycyA9IGMoImdyb3VwMiIsICJncm91cDEiLCAiZ3JvdXAiLCAiZGlzcmF0ZSIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZS5uYW1lID0gImJldGFfZCIsIHZhcmlhYmxlLm5hbWUgPSAiYmV0YWtlcm5lbCIpDQoNCmFsbGJldGFzLm1lbHQubGl0aCRFX1YgPC0gYWxsYmV0YXMubWVsdC5saXRoJGJldGFfZCp2aXJudW0NCmFsbGJldGFzLm1lbHQubGl0aCRFX0hWIDwtIGFsbGJldGFzLm1lbHQubGl0aCRiZXRhX2QqdmlybnVtKmhvc3RudW0NCg0KZ2dwbG90KGFsbGJldGFzLm1lbHQsIGFlcyhkaXNyYXRlLCB5ID0gRV9WLCBjb2xvcj1ncm91cDIpKSArIA0KICBnZW9tX2xpbmUoc2l6ZT0xKSsNCiAgc2NhbGVfeV9sb2cxMCgNCiAgICAgICAgYnJlYWtzID0gc2NhbGVzOjp0cmFuc19icmVha3MoImxvZzEwIiwgZnVuY3Rpb24oeCkgMTBeeCwgbj00KSwNCiAgICAgICAgbGFiZWxzID0gc2NhbGVzOjp0cmFuc19mb3JtYXQoImxvZzEwIiwgc2NhbGVzOjptYXRoX2Zvcm1hdCgxMF4ueCkpKSArDQogIHNjYWxlX3hfbG9nMTAoDQogICAgICAgIGJyZWFrcyA9IHNjYWxlczo6dHJhbnNfYnJlYWtzKCJsb2cxMCIsIGZ1bmN0aW9uKHgpIDEwXngsIG49NyksDQogICAgICAgIGxhYmVscyA9IHNjYWxlczo6dHJhbnNfZm9ybWF0KCJsb2cxMCIsIHNjYWxlczo6bWF0aF9mb3JtYXQoMTBeLngpKSkgKw0KICBhbm5vdGF0aW9uX2xvZ3RpY2tzKCkgKyBmYWNldF9ncmlkKH5iZXRha2VybmVsKQ0KDQojc3Vic2V0IGRhdGENCg0KZ3JhcGgxIDwtIHN1YnNldChhbGxiZXRhcy5tZWx0LCBiZXRha2VybmVsICVpbiUgYyAoImJldGFfQk0iLCAiYmV0YV9EUyIsICJiZXRhX0JNX0RTIikpDQpncmFwaDIgPC0gc3Vic2V0KGFsbGJldGFzLm1lbHQsIGJldGFrZXJuZWwgJWluJSBjICgiYmV0YV90dXJiIiwgImJldGFfRFNfdHVyYiIsICJiZXRhX0JNX3R1cmIiLCAiYmV0YV9hbGwiKSkNCmxpdGggPC0gc3Vic2V0KGFsbGJldGFzLm1lbHQubGl0aCwgYmV0YWtlcm5lbCAlaW4lIGMoImJldGFfRFNfdHVyYi5saXRoIikgJiBncm91cDEgJWluJSBjKCJjYWxjaWZpZWQiKSkNCmxpdGgkbWFpbmdyb3VwIDwtIGxpdGgkZ3JvdXAyDQpsaXRoJGdyb3VwMiA8LSBhcy5mYWN0b3IocGFzdGUobGl0aCRtYWluZ3JvdXAsIGxpdGgkZ3JvdXAsIHNlcD0nLScpKQ0KDQpnZ3Bsb3QoZ3JhcGgxLCBhZXMoZ3JvdXAyLCB5ID0gRV9WLCBjb2xvcj1iZXRha2VybmVsKSkgKyANCiAgZ2VvbV9qaXR0ZXIoc2l6ZT01KSsNCiAgc2NhbGVfeV9sb2cxMCgNCiAgICAgICAgYnJlYWtzID0gc2NhbGVzOjp0cmFuc19icmVha3MoImxvZzEwIiwgZnVuY3Rpb24oeCkgMTBeeCwgbj00KSwNCiAgICAgICAgbGFiZWxzID0gc2NhbGVzOjp0cmFuc19mb3JtYXQoImxvZzEwIiwgc2NhbGVzOjptYXRoX2Zvcm1hdCgxMF4ueCkpKSArDQogIGFubm90YXRpb25fbG9ndGlja3Moc2lkZXMgPSAibCIpKw0KICB0aGVtZV9QdWJsaWNhdGlvbigpICsNCiAgbGFicyh5ID0gZXhwcmVzc2lvbigidmlyYWwgZW5jb3VudGVycyAiIH4gZGF5Xi0xfmNlbGxeLTEpKSArDQogIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSkNCg0KZ3JhcGgxLnN1bSA8LSBzdW1tYXJ5U0UgKGdyYXBoMSwgbWVhc3VyZXZhciA9ICJFX1YiLCBncm91cHZhcnMgPSBjKCJiZXRha2VybmVsIiwgImdyb3VwMiIpKQ0KDQpnZ3Bsb3QoZ3JhcGgxLnN1bSwgYWVzKGdyb3VwMiwgeSA9IEVfViwgY29sb3I9YmV0YWtlcm5lbCkpICsgDQogIGdlb21fcG9pbnQoc2l6ZT01LCAgcG9zaXRpb249cG9zaXRpb25fZG9kZ2UoMC4yKSkrDQogIHNjYWxlX3lfbG9nMTAoDQogICAgICAgIGJyZWFrcyA9IHNjYWxlczo6dHJhbnNfYnJlYWtzKCJsb2cxMCIsIGZ1bmN0aW9uKHgpIDEwXngsIG49NCksDQogICAgICAgIGxhYmVscyA9IHNjYWxlczo6dHJhbnNfZm9ybWF0KCJsb2cxMCIsIHNjYWxlczo6bWF0aF9mb3JtYXQoMTBeLngpKSkgKw0KICBhbm5vdGF0aW9uX2xvZ3RpY2tzKHNpZGVzID0gImwiKSsNCiAgdGhlbWVfUHVibGljYXRpb24oKSArDQogIGxhYnMoeSA9IGV4cHJlc3Npb24oInZpcmFsIGVuY291bnRlcnMgIiB+IGRheV4tMX5jZWxsXi0xKSkgKw0KICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpDQogIA0KZ2dwbG90KGRhdGE9YWxsYmV0YXMubWVsdCAlPiUgZmlsdGVyKGJldGFrZXJuZWwgJWluJSBjKCJiZXRhX3R1cmIiLCAiYmV0YV9hbGwiKSksIA0KICAgICAgIGFlcyh4PWRpc3JhdGUseSA9IEVfViwgY29sb3I9Z3JvdXAyLCBsaW5ldHlwZT1iZXRha2VybmVsKSkgKyANCiAgZ2VvbV9saW5lKHNpemU9MSwgcG9zaXRpb249cG9zaXRpb25faml0dGVyKHc9MC4wMiwgaD0wKSkrDQogICBzY2FsZV95X2xvZzEwKA0KICAgICAgICBicmVha3MgPSBzY2FsZXM6OnRyYW5zX2JyZWFrcygibG9nMTAiLCBmdW5jdGlvbih4KSAxMF54LCBuPTQpLA0KICAgICAgICBsYWJlbHMgPSBzY2FsZXM6OnRyYW5zX2Zvcm1hdCgibG9nMTAiLCBzY2FsZXM6Om1hdGhfZm9ybWF0KDEwXi54KSkpICsNCiAgc2NhbGVfeF9sb2cxMCgNCiAgICAgICAgYnJlYWtzID0gc2NhbGVzOjp0cmFuc19icmVha3MoImxvZzEwIiwgZnVuY3Rpb24oeCkgMTBeeCwgbj03KSwNCiAgICAgICAgbGFiZWxzID0gc2NhbGVzOjp0cmFuc19mb3JtYXQoImxvZzEwIiwgc2NhbGVzOjptYXRoX2Zvcm1hdCgxMF4ueCkpKSArDQogIGFubm90YXRpb25fbG9ndGlja3MoKSsNCiAgdGhlbWVfUHVibGljYXRpb24oKSsNCiAgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLCBsZWdlbmQua2V5LndpZHRoPXVuaXQoMiwiY20iKSkrDQogIGd1aWRlcyhsaW5ldHlwZT1ndWlkZV9sZWdlbmQobnJvdyAgPTQpLCBjb2xvdXI9Z3VpZGVfbGVnZW5kKG5yb3c9NCxieXJvdz1UUlVFKSkgKw0KICBsYWJzKHkgPSBleHByZXNzaW9uKCJ2aXJhbCBlbmNvdW50ZXJzICIgfiBkYXleLTF+Y2VsbF4tMSksIHggPSBleHByZXNzaW9uKCJkaXNzaXBhdGlvbiByYXRlICJ+KG1eMn5zXi0zKSkpICsNCiAgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpKQ0KICANCmdncGxvdChkYXRhPWFsbGJldGFzLm1lbHQgJT4lIGZpbHRlcihiZXRha2VybmVsICVpbiUgYygiYmV0YV9hbGwiKSksIA0KICAgICAgIGFlcyh4PWRpc3JhdGUseSA9IEVfViwgY29sb3I9Z3JvdXAyKSkgKyANCiAgZ2VvbV9saW5lKHNpemU9MSwgcG9zaXRpb249cG9zaXRpb25faml0dGVyKHc9MC4wMiwgaD0wKSkrDQogIGdlb21fbGluZShkYXRhID0gbGl0aCwgYWVzKHk9IEVfViwgY29sb3I9Z3JvdXAyKSkgKw0KICAgc2NhbGVfeV9sb2cxMCgNCiAgICAgICAgYnJlYWtzID0gc2NhbGVzOjp0cmFuc19icmVha3MoImxvZzEwIiwgZnVuY3Rpb24oeCkgMTBeeCwgbj0yKSwNCiAgICAgICAgbGFiZWxzID0gc2NhbGVzOjp0cmFuc19mb3JtYXQoImxvZzEwIiwgc2NhbGVzOjptYXRoX2Zvcm1hdCgxMF4ueCkpKSArDQogIHNjYWxlX3hfbG9nMTAoDQogICAgICAgIGJyZWFrcyA9IHNjYWxlczo6dHJhbnNfYnJlYWtzKCJsb2cxMCIsIGZ1bmN0aW9uKHgpIDEwXngsIG49NyksDQogICAgICAgIGxhYmVscyA9IHNjYWxlczo6dHJhbnNfZm9ybWF0KCJsb2cxMCIsIHNjYWxlczo6bWF0aF9mb3JtYXQoMTBeLngpKSkgKw0KICBhbm5vdGF0aW9uX2xvZ3RpY2tzKCkrDQogIHRoZW1lX1B1YmxpY2F0aW9uKCkgKw0KICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksIGxlZ2VuZC5rZXkud2lkdGg9dW5pdCgxLCJjbSIpKSsNCiAgbGFicyh5ID0gZXhwcmVzc2lvbigidmlyYWwgZW5jb3VudGVycyAiIH5kYXleLTF+Y2VsbF4tMSksIHggPSBleHByZXNzaW9uKCJkaXNzaXBhdGlvbiByYXRlICJ+KG1eMn5zXi0zKSkpICsNCiAgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpKQ0KDQoNCmdncGxvdChkYXRhPWFsbGJldGFzLm1lbHQgJT4lIGZpbHRlcihiZXRha2VybmVsICVpbiUgYygiYmV0YV9hbGwiKSksIA0KICAgICAgIGFlcyh4PWRpc3JhdGUseSA9IEVfSFYsIGNvbG9yPWdyb3VwMikpICsgDQogIGdlb21fbGluZShzaXplPTEsIHBvc2l0aW9uPXBvc2l0aW9uX2ppdHRlcih3PTAuMDIsIGg9MCkpKw0KICBnZW9tX2xpbmUoZGF0YSA9IGxpdGgsIGFlcyh5PSBFX0hWLCBjb2xvcj1ncm91cDIpKSArDQogICBzY2FsZV95X2xvZzEwKA0KICAgICAgICBicmVha3MgPSBzY2FsZXM6OnRyYW5zX2JyZWFrcygibG9nMTAiLCBmdW5jdGlvbih4KSAxMF54LCBuPTIpLA0KICAgICAgICBsYWJlbHMgPSBzY2FsZXM6OnRyYW5zX2Zvcm1hdCgibG9nMTAiLCBzY2FsZXM6Om1hdGhfZm9ybWF0KDEwXi54KSkpICsNCiAgc2NhbGVfeF9sb2cxMCgNCiAgICAgICAgYnJlYWtzID0gc2NhbGVzOjp0cmFuc19icmVha3MoImxvZzEwIiwgZnVuY3Rpb24oeCkgMTBeeCwgbj03KSwNCiAgICAgICAgbGFiZWxzID0gc2NhbGVzOjp0cmFuc19mb3JtYXQoImxvZzEwIiwgc2NhbGVzOjptYXRoX2Zvcm1hdCgxMF4ueCkpKSArDQogIGFubm90YXRpb25fbG9ndGlja3MoKSsNCiAgdGhlbWVfUHVibGljYXRpb24oKSArDQogIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwgbGVnZW5kLmtleS53aWR0aD11bml0KDEsImNtIikpKw0KICBsYWJzKHkgPSBleHByZXNzaW9uKCJ2aXJhbCBlbmNvdW50ZXJzICIgfiBjbV4tM35kYXleLTEpLHggPSBleHByZXNzaW9uKCJkaXNzaXBhdGlvbiByYXRlICJ+KG1eMn5zXi0zKSkpICsNCiAgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpKQ0KDQphbGxiZXRhcy5tZWx0LmRyb3BuYyA8LSBhbGxiZXRhcy5tZWx0IFshYWxsYmV0YXMubWVsdCRncm91cDIgPT0ibmFrZWQvY2FsY2lmaWVkIHVuY2VydGFpbiIsIF0NCmFsbGJldGFzLm1lbHQuZHJvcG5jJGdyb3VwMiA8LSBmYWN0b3IoYWxsYmV0YXMubWVsdC5kcm9wbmMkZ3JvdXAyLCBsZXZlbHMgPSBjKCJuYWtlZCIsICJtb2RlcmF0ZWx5IGNhbGNpZmllZCIsICJtb2RlcmF0ZWx5IGNhbGNpZmllZC1saXRoIiwgInN0cm9uZ2x5IGNhbGNpZmllZCIsICJzdHJvbmdseSBjYWxjaWZpZWQtbGl0aCIpKQ0KDQphbGxiZXRhcy5tZWx0LmRyb3BuYyA8LSBhbGxiZXRhcy5tZWx0LmRyb3BuYyU+JQ0KICBhcnJhbmdlKGZhY3Rvcihncm91cDIsIGMoIm5ha2VkIiwgIm1vZGVyYXRlbHkgY2FsY2lmaWVkIiwgIm1vZGVyYXRlbHkgY2FsY2lmaWVkLWxpdGgiLCAic3Ryb25nbHkgY2FsY2lmaWVkIiwgInN0cm9uZ2x5IGNhbGNpZmllZC1saXRoIikpKQ0KDQpnZ3Bsb3QoZGF0YT1hbGxiZXRhcy5tZWx0LmRyb3BuYyAlPiUgZmlsdGVyKGJldGFrZXJuZWwgJWluJSBjKCJiZXRhX2FsbCIpKSwgDQogICAgICAgYWVzKHg9ZGlzcmF0ZSx5ID0gRV9WLCBjb2xvcj1ncm91cDIpKSArIA0KICAgIGdlb21fbGluZShzaXplPTEsIHBvc2l0aW9uPXBvc2l0aW9uX2ppdHRlcih3PTAuMDIsIGg9MCkpKw0KICAgIGdlb21fbGluZShkYXRhID0gbGl0aCwgYWVzKHk9IEVfViwgY29sb3I9Z3JvdXAyKSkgKw0KICAgIHNjYWxlX3lfbG9nMTAoDQogICAgICAgIGJyZWFrcyA9IHNjYWxlczo6dHJhbnNfYnJlYWtzKCJsb2cxMCIsIGZ1bmN0aW9uKHgpIDEwXngsIG49MiksDQogICAgICAgIGxhYmVscyA9IHNjYWxlczo6dHJhbnNfZm9ybWF0KCJsb2cxMCIsIHNjYWxlczo6bWF0aF9mb3JtYXQoMTBeLngpKSkgKw0KICAgIHNjYWxlX3hfbG9nMTAoDQogICAgICAgIGJyZWFrcyA9IHNjYWxlczo6dHJhbnNfYnJlYWtzKCJsb2cxMCIsIGZ1bmN0aW9uKHgpIDEwXngsIG49NyksDQogICAgICAgIGxhYmVscyA9IHNjYWxlczo6dHJhbnNfZm9ybWF0KCJsb2cxMCIsIHNjYWxlczo6bWF0aF9mb3JtYXQoMTBeLngpKSkgKw0KICAgIGFubm90YXRpb25fbG9ndGlja3MoKSsNCiAgICB0aGVtZV9QdWJsaWNhdGlvbigpICsNCiAgICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksIGxlZ2VuZC5rZXkud2lkdGg9dW5pdCgxLCJjbSIpKSsNCiAgbGFicyh5ID0gZXhwcmVzc2lvbigidmlyYWwgZW5jb3VudGVycyAiIH5kYXleLTF+Y2VsbF4tMSksIHggPSBleHByZXNzaW9uKCJkaXNzaXBhdGlvbiByYXRlICJ+KG1eMn5zXi0zKSkpICsNCiAgICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpKyBndWlkZXMobGluZXR5cGU9Z3VpZGVfbGVnZW5kKG5yb3cgID00KSwgY29sb3VyPWd1aWRlX2xlZ2VuZChucm93PTQsYnlyb3c9VFJVRSkpIA0KDQp3cml0ZS54bHN4KGFsbGJldGFzLm1lbHQuZHJvcG5jLCBmaWxlID0gIlBvc3Rkb2MtUi9FeHBvcnRlZCBUYWJsZXMvYWxsYmV0YXMueGxzeCIpDQoNCg0KDQoNCg0KYGBgDQoNCmZvciBzYXZpbmcganVzdCB0aGUgUiBmaWxlDQpgYGB7cn0NCnJlcXVpcmUgKGtuaXRyKQ0KcHVybChpbnB1dCA9ICJEOi9SIHByb2dyYW0vUG9zdGRvYy1SL1IgTm90ZWJvb2svRGVjIDIwMTgvYmV0YSBrZXJuZWwgMTgxMjA0LlJtZCIpICNvdXRwdXQgZmlsZSB3aWxsIGJlIG9uIHRoZSBtYWluIFIgZGlyZWN0b3J5IGFuZCBzYXZlZCB3aXRoIHRoZSBzYW1lIGZpbGUgbmFtZQ0KYGBgDQoNCmBgYHtyfQ0KDQoNCg0KYGBgDQoNCg==